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


题外话:关于const和指针的内容,个人感觉中文表达的确更难理解一点,比如const int **x,个人感觉“x is a pointer to pointer to const int”比“x是一个指向指向只读int的指针的指针”好理解一点。这可能和英语惯用定语后置,而中文翻译通常定语前置有关。


最后引用两句话:
不要添乱,立刻解散ISO工作组!
我们做的第一件事,就是杀光语言律师。
(溜了溜了

■网友
以上是C++03标准中关于不允许如此转换所举的一个例子。允许此种转换的代价是不能保证常量安全。
■网友
居然只有警告:这是很危险的,而且我印象中是违反标准中的隐式类型转换规则的.....比如void test(const char* target, const char** result) { *result = target;}这个test是多么正常的一个函数,但是如果你能够把char**传给result,那么你就简单的可以把target前面的const给去掉了......顺便这个在类型系统里面叫做not sound嗯
■网友
你可以在期望一个const T类型指针的地方使用指向T类型的指针。
比如,下面的代码编译是可以通过的。
voidfoo(const char*){}intmain(int argc, char **argv){ char p; foo(\u0026amp;p); return 0;}但是请注意,这一规则,或者说一个显式的例外,允许指针类型中的轻微不匹配,是不允许递归地应用,
只可以在最顶层(top level)。所以对于const char**,它是一个指向常量的指针的指针,不可以应用上面这一规则。
不允许将一个char**类型的值,赋值给一个const char**类型的指针,可以说原因有些模糊。
const限定符存在时,编译器将帮助您保证常量不被修改。这就是为什么你可以将一个char*类型赋值给const char*类型,但是反过来就不行。
假定你将执行下面一系列的赋值操作:
\tconst char c = \u0026#39;x\u0026#39;;\t\t/* 1 */\tchar *p1;\t\t\t/* 2 */\tconst char **p2 = \u0026amp;p1;\t\t/* 3 */\t*p2 = \u0026amp;c;\t\t\t/* 4 */\t*p1 = \u0026#39;X\u0026#39;;\t\t\t/* 5 */在第三行,将一个char**类型赋值给const char**类型(编译器会报错)。
在第四行,将一个const char*类型(\u0026amp;c)赋值给const char* (*p2)类型,这是合法的.
在第五行,修改一个char*类型的指针,这理应合法的。但是p1指向c,而c是一个const char类型。你会发现在第四行*p2实际上就是p1,因为通过第三行的操作,p2指向了p1
到这里你会明白,为什么第三行的赋值操作是非法的。如果第三行操作合法,将会导致第五行的结论。
将char**类型的赋值给const char**类型,不会导致直接的危险。但是正如上面的推导,它会产生一种情形-p2最终所指向的值不能被修改,这一声明不满足。
【为啥不能把 char ** 传给需要 char const ** 的函数】 在C语言中,如果你必须将限定符不相容的指针赋值给非第一级间接使用,则必须使用显式强制类型转换。然而,需要做这样的类型强制转换可能意味这背后隐藏着更深的问题,只是这个强制类型转换并不能解决这个问题。

■网友
这个倒是C语言一个很深的坑,很多人都感到费解,一两句话很难说清。我记得有人就此专门写过一篇论文。简单地讲,就是char **与 const char **类型并不兼容(imcompatble)。进一步说,就是如果C语言允许这样,就会产生与引人const这个关键字本意自相矛盾的结果,const就变得一点意义都没有了。譬如,假如可以把char ** 赋值给 const char **,那么后者的*运算得到的是一个char *,这时就会发现const char **中的那个const毫无意义了比如:


推荐阅读