1. 二级常量指针作形参的传参问题
-
一个函数的形参为指向常量的指针,比如:
const int*
给它传递int*
的参数,编译是可以通过的,不需强制转换。 -
如果是
const int**
的参数,给它传递int**
的参数,则编译不能通过,需要进行强制转换。
why?
C++
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;
}
2. 解析
-
做项目中碰到类似问题,加个强制转换就行了,但是不理解为什么一级常量指针不用加强制转换直接传非常量的指针就行,但同样的情况对于二级指针就不行。
-
在csdn网友的热心帮助下,弄明白了这个问题,现总结如下(以下为我认为最清楚最明白的一条回答):
为了防止指针指向的常量被修改,C标准对于指针间赋值有一个规定,就是左值必须包含右值的所有限定词。这就限定了一个指向const对象的指针不能赋值给指向非const对象的指针,但反过来就允许。这个规定初看上去非常合理,但其效用其实只限于一级指针,二级指针间的赋值即使满足规定也不再安全,下面举个例子:
C++
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也是非法的。