foo(const char **p){}
main(int argc, char **argv)
{
foo(argv); //error
}
在vc6.0中会报以下错误:
error C2664: 'foo' : cannot convert parameter 1 from 'char ** ' to 'const char ** '
首先明确一下char * const、const char *和char * 的区别:
char * const 指向字符的静态指针,即const pointer to char
const char * 指向静态字符的指针,即pointer to const char
char * 指向字符的指针,即pointer to char
三个最大的区别是什么可以改变,什么不能改变。
很明显,第一种“指针”是不能变的,但是指针所指向的值can be changed,because the pointer is const type;
第二种指针可以变,但是针所指向的值can't be changed,because the char is const type,the pointer isnot;
那么第三种呢?其实第三种和第一种是一样的,默认char * 即为char * const,所以平时很少见到有写成char * const。
明确了三者的区别我们再来看一个例子:
char *cp;
const char * ccp;
ccp = cp;
1) 左操作数ccp是指向 有const限定符的char 类型 的指针。
2) 右操作数cp 是指向 无限定符的char 类型 的指针。
3) 显然char类型和char类型是相容的,ccp 所指向的类型具有cp所指向类型的限定符(无) 和自身的限定符const.
所以 ccp = cp 是合法的,相反 cp = ccp 就会警告
现在再回头看之前的问题:
const char** 是一个没有限定符的指针类型,它的类型是"指向有const限定符的char类型的指针的指针"。
而char ** 的类型是“指向char类型的指针的指针”
char ** 和 const char ** 都是没有限定符的指针类型,但它们所指向的类型不一样( 前者指向char*, 后者指向 const char*), 因此它们是不相容的。
根据ANSI C标准:要使赋值形式合法,必须满足下列条件之一:
1、两个操作数都是指向有限定符或无限定符的相容类型的指针;
2、左边的指针所指向的类型必须具有右边指针所指向类型的全部限定符。
所以之前的那个函数调用的形参的赋值是错误的,编译不过也是正常的。。。
所有这些问题都与一个东西有关,那就是“const”,const到底妙处在什么地方呢???
下面引用在《c编程专家》中的原话:
关键字const并不能把变量变成常量!在一个符号前加上const限定符只是表示这个符号不能被赋值,也就是它的值对于这个符号来说是只读的,但它并不能防止通过程序的内部(甚至外部)的方法来修改这个值,const最有用指出就是它来限定函数的形参,这样该函数将不会修改实参指针所指的数据,但其他的函数却可能会修改它。这也许就是c和c++中const最一般的用法。
const和*的组合通常只用于在数组形式的参数中模拟传值调用。它声称:“我给你一个指向它的指针,但你不能修改它”,这个约定类似于极为常见的void *的用法,尽管在理论上它可以用于任何情形,但通常被限制于把指针从一种类型转换为另一种类型。
const关键字原先如果命名为readonly就好多了。。。