二级常量指针作形参的传参问题

来源:互联网 发布:手机外汇看盘软件 编辑:程序博客网 时间:2024/06/04 18:18

一个函数的形参为指向常量的指针,比如:const int*
给它传递int*的参数,编译是可以通过的,不需强制转换。
如果是const int**的参数,
给它传递int**的参数,则编译不能通过,需要进行强制转换。
why?

例如:


void fun1(const int* a) {return;}
void fun2(const int** a) {return;}
int main()
{
  
int a = 5;
  
int* b = &a;
  
int** c = &b;
   fun1(b);   
// 可以通过
   fun2(c);    // 不可以通过
   return 0;
}

做项目中碰到类似问题,加个强制转换就行了,但是不理解为什
么一级常量指针不用加强制转换直接传非常量的指针就行,但同
样的情况对于二级指针就不行。在csdn网友的热心帮助下,弄明白
了这个问题,现总结如下:
以下为我认为最清楚最明白的一条回答:
为了防止指针指向的常量被修改,C标准对于指针间赋值有一个规定,
就是左值必须包含右值的所有限定词。这就限定了一个指向const对象
的指针不能赋值给指向非const对象的指针,但反过来就允许。这个规
定初看上去非常合理,但其效用其实只限于一级指针,二级指针间的
赋值即使满足规定也不再安全,下面举个例子: 

const int i=10;
const int **p1;
int *p2;
p1 = &p2;
*p1 = &i;
*p2 = 20;

现在你会发现,作为常量的i的值被修改了。
i的值被修改的关键原因在*p1=&i;这一句,&i是一个指向常量的一级地址,
如果没有二级指针p1,受限于上述规定,作为左值接受这个一级地址的指
针就必须也是一个指向常量的一级指针,于是就不能进行下一步赋值20的
操作。因此,正由于指向 const对象的二级指针p1的出现,使得*p1也是
一个指向const的指针,于是*p1=&i能够合法地运行,常量i的值被修改也
就成了一个预想中的结果了。有鉴于此,某些编译器也会限定非const
二级指针之间的赋值,规定上面的p1=&p2也是非法的。