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


C专家编程的1.9节,看完之后我很迷茫,没明白讲的,讲的什么鬼???《C专家编程》对于这个问题的讨论大概是下面的流程,只是没有解释地那么详细。
《C专家编程》引用的是C89/C90标准,本回答引用的是C99标准,但是原因与结论是一致的,只是引用的章节发生了变化

首先根据C99中关于函数调用的规定:
6.5.2.2 Function calls...2 ...Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.可知,函数调用时的传参就类似于赋值,要遵守赋值的规则。
因此,这个函数调用时出现的问题可以视为一个赋值问题:为什么不能将char **赋予const char**?
转换为赋值问题后,接下来看看C99标准关于赋值的相关规定中,对应此情形的部分:
6.5.16 Assignment operators... 6.5.16.1 Simple assignment ... Constraints 1 One of the following shall hold: ...both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;由上可知,假设有两个指针,同时满足以下两个条件,则右侧指针的值可以赋予左侧指针:
两者各自指向的类型,在去掉const/volatile等限定符后,是相同类型。(根据C99的6.2.7节,“compatible type”就是两个相同的类型,所以此处使用“相同类型”替代“compatible type”以方便理解)左侧所指向的类型,包含右侧所指向的类型所拥有的所有限定符。也就是说,下面这样是可以的:
int *x, *y;x = y; //OK,左侧x和右侧y都指向int,是相同类型,满足条件1 //左侧x指向的类型(int)包含右侧y指向的类型(int)的所有限定符,满足条件2下面这样也是可以的:
const int *x;int *y;x = y; //OK, 左侧x指向的const int去掉const限定符后,与右侧y指向的int为相同类型,满足条件1 //左侧x指向的类型(const int)包含右侧y指向的类型(int)的所有限定符,满足条件2const int *z;x = z; //OK,左侧x和右侧z都指向const int,都去掉const限定符后,都为int,满足条件1 //左侧x指向的类型(const int)包含右侧z指向的类型(const int)的所有限定符,满足条件2同理,下面这样也是可以的:
const int *x;const int *const y;x = y; //OK,左侧x和右侧y都指向const int,都去掉const限定符后,都为int,满足条件1 //左侧x指向的类型(const int)包含右侧y指向的类型(const int)的所有限定符,满足条件2 //不过注意,y自身的const(即*const)表示y自身是只读的、不可被赋值,所以y=x是不允许的
回到我们探讨的问题上:为什么将一个char**赋予const char **不满足赋值的这条规定?(将char **赋予const char**,不符合此处未列出的其他规定的基准情形,因此它显然不满足其他规定,我们只需要找出这条规定没被满足的原因即可)
显然,将char **赋予const char **要么是没满足条件1,要么是没满足条件2。而从编译器的报错信息“argument is incompatible with prototype”来看,它没满足条件1。
所以接下来只需要解释,为什么这样赋值不满足条件1。
我们先把问题例子写出来以便后面引用:
const char **x;char **y;x = y; //错误显然,x所指向的类型是“const char *”,y所指向的类型是“char*”,因为不满足条件1,于是问题简化成:为什么char *和const char *不是“compatible type”?


推荐阅读