为啥不能把 char ** 传给需要 char const ** 的函数( 三 )


根据前面提到过的C99的6.2.7节:
6.2.7 Compatible type and composite type Two types have compatible type if their types are the same.可知,当两个类型相同时,它们才是“compatible type”。
于是问题再次转换为:为什么char *和const char*是不同的类型?
参考C99的6.2.5节:
6.2.5 Types ... 28 EXAMPLE 1 The type designated as "float *" has type "pointer to float". Its type category is pointer, not a floating type. The const-qualified version of this type is designated as "float * const" whereas the type designated as "const float *" is not a qualified type — its type is "pointer to const qualified float" and is a pointer to a qualified type.可以知道:
“char *”是“指向char的指针”类型“const char*”是“指向const char的指针”类型也就是说,两者都是指针,但两者指向的类型不同,一个指向“char”,一个指向“const char”,所以两者不是相同的类型,也就不是“compatible type”。
至此,倒推回去,问题的原因就清楚了:char *和const char*是不同的类型,所以将char**赋予const char **时,未满足赋值操作的规定。

到这一步,肯定还有人会困惑,比如为什么下面这样没有错:
const char *x;char *y;x = y; //不是说x和y是不同的类型吗?为什么这个赋值合法?那是因为,x和y虽然是不同的类型,但是将y的值赋给x符合我们最上面提到的条件1和条件2:
左侧和右侧指向的类型,在去掉限定符后,是相同类型:左侧x指向的const char在去掉const后,与右侧y指向的char是相同类型。左侧指向的类型拥有右侧y指向的类型的所有限定符:const char包含char的所有限定符。强调一下,上例中的x和y的确是不同类型,是因为满足赋值的要求,所以可以赋值。
为了强化理解,再次拿出问题例子来对比一下:
const char **x;char **y;x = y; //错误注意,这里的赋值错误,不是因为x和y是不同类型,而是因为它不满足赋值的要求:
x指向的是类型是“char *”,去掉(该类型的)限定符后依然是“char *”,y指向的类型是“const char *”,去掉(该类型的)限定符后依然是“const char *”,去掉限定符后,“char *”和“const char *”仍然不是相同类型,不满足条件1。

补充一点可能对小白有帮助的提示:“char *”的有限定符形式应该是“char * const”,而不是“const char *”,“const char *”的有限定符形式是“const char *const”。
再举一个可能有帮助也可能多余的例子……
char* const* x;char** y = \u0026amp;b;x = y;//OK,左侧x指向的char * const去掉const后,与右侧y指向的char *为相同类型,满足条件1 //左侧x指向的类型(char * const)包含右侧y指向的类型(char *)的所有限定符,满足条件2
如果要问为什么C标准要对指针和const的情况做如此规定,可以看看C99中举的例子:
6.5.16.1 Simple assignment ... 6 EXAMPLE 3 Consider the fragment:const char **cpp;char *p;const char c = \u0026#39;A\u0026#39;;cpp = \u0026amp;p; //constraint violation*cpp = \u0026amp;c; //valid*p = 0; //validThe first assignment is unsafe because it would allow the following valid code to attempt to change the value of the const object c.如果允许将char **赋予const char**,那么上面的cpp=\u0026amp;p就是合法的,会导致接下来的一系列合法操作,产生一个非法结果(修改了const char类型的变量c),因此不能允许cpp=\u0026amp;p。


推荐阅读