本文可能让你想起谭浩强, 那就这样吧.
“参数是 const int**
, 我传入 int**
居然警告??”
代码
我们简化为赋值, 传参是一样的.
int main() {
int** n2;
const int** c2 = n2;
int* n1;
const int* c1 = n1;
}
使用 gcc 按照 C99 标准编译
$ gcc -ansi -Wpedantic -std=c99 test.c
test.c: In function ‘main’:
test.c:3:20: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
const int** c2 = n2;
^
可以看到, 第一个赋值出现了 “incompatible pointer” 而第二个没有.
原因
将类型形式化的写出来, 大概是
* n2: pointer_to(pointer_to(int))
* c2: pointer_to(pointer_to(const int))
* n1: pointer_to(int)
* c1: pointer_to(const int)
注意最开始的 const 修饰的是 int 而非指针.
相关的 C99 条款有
- (C99 6.7.5.1.2) For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
- (C99 6.3.2.3.2) For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.
- (C99 6.7.3.9) For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.
- (C99 6.5.16.1.1) [Simple assignment – 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; (注: 可以参考 PLDI’99 A Theory for Type Qualifiers, 这里就是要求 negative qualifier 上的 subtyping 关系)
因此, 按照第 2 条, pointer_to(int)
可以被转换成 pointer_to(const int)
.
所以 c1 = n1
是允许的.
按照第 3 条, int
和 const int
并不 compatible,
因此按照第 1 条, pointer_to(int)
和 pointer_to(const int)
不 compatible,
因此按照第 4 条, 赋值不允许, 因为 pointer_to(int)
和 pointer_to(const int)
不 compatible.
所以 gcc 的报错信息是对的.