C语言中为什么不能把char**赋给const char**
这是我在知乎回答的一个问题.
这个问题是C中的一个深坑,首先说结论:
char ** 和 const char ** 是两个不相容(incompatible)的类型,可以理解为不能直接赋值在C11的6.5.2.2 Function calls中有如下内容
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.翻译:每个实参都应该具有自己的类型,这样它的值就可以赋给对应非完全限定版本形参类型的对象
也就是说:参数传递的过程和赋值是类似的.
再看6.5.16.1 Simple assignment中的约束条件
Constraints简单来说就是两个操作数都是指向有限定符或无限定符的相容的类型的指针,左边的指针必须有右边指针指向类型的全部限定符时赋值合法
1 One of the following shall hold:112)
(......省略......)
-- the left operand has atomic, qualified, or unqualified pointer type, and (considering
the type the left operand would have after lvalue conversion) 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;
(......省略......)
正是因为这条约束的存在,所以能将实参char* 赋给const char*,比如下面这段用于讲解的代码:
char *cp;
const char *ccp;
ccp = cp;
右操作数cp是指向无const限定符的char的指针
char和char是相容的类型,左指针具有右指针指向类型的全部限定符(右指针指向的类型没有限定符)
因此这个赋值是合法的.
注意反过来就不行了.
6.5.16.1 Simple assignment中其他约束条件都不能说明char** 赋值给const char ** 是合法的.最有可能证明其合法的是上面写的那个约束条件.
然而这个"最有可能证明"的约束条件并不能证明该赋值是合法的.
首先看6.2.5 Types中的例子
29 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.这个例子是说const float * 类型并不是一个有限定符的类型,它是一个没有限定符的指针,指向的是有const限定符的float类型数据.也就是说const修饰的是指向的float而不是指针本身.
类似的,char ** 和const char **都是没有限定符的指针.
char ** 指向的是没有限定修饰符的指针char *
const char ** 指向的是没有限定修饰符的指针const char *
但是char * 和const char * 是不相容的,约束条件要求被指向的类型,无论有没有限定符,但是必须是相容的,显然char * 和const char *是两种不同的指针.
尽管char * 和const char * 所指向的类型是相容的,而且可以把前一个指针的值赋给后一个指针,但是这并不能说明这两个指针类型是相容的.
总之,char * 和const char * 不相容,这和那个"最有可能证明"的约束条件相违背,所以没有任何约束条件能证明可以把char **的值赋给const char **.
所以编译器会显示那个警告.因为这两个指针根本不是同一类型的指针.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。