C11标准ISO / IEC 9899:2011(E)规定了第6.5.16.1 / 1条中简单分配的以下限制:
One of the following shall hold:
- the left operand has atomic,qualified,or unqualified arithmetic type,and the right has
arithmetic type;- the left operand has an atomic,or unqualified version of a structure or union
type compatible with the type of the right;- the left operand has atomic,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;- the left operand has atomic,and (considering
the type the left operand would have after lvalue conversion) one operand is a pointer
to an object type,and the other is a pointer to a qualified or unqualified version of
void,and the type pointed to by the left has all the qualifiers of the type pointed to
by the right;- the left operand is an atomic,or unqualified pointer,and the right is a null
pointer constant; or- the left operand has type atomic,or unqualified
_Bool
,and the right is a pointer.
我感兴趣的是双方都是不同于void的不兼容类型的指针.如果我理解正确,这应该至少是调用UB,因为它违反了这个约束.不兼容类型的一个例子应该是(根据§6.2.7和§6.7.2)int和double.
因此,以下程序应违反:
int main(void) { int a = 17; double* p; p = &a; (void)p; }
gcc和clang都警告“-Win兼容指针类型”,但不要中止编译(使用-std = c11 -Wall -Wextra -pedantic进行编译).
类似地,以下程序只会导致“-Wint-conversion”警告,而编译就好了.
int main(void) { int a; double* p; p = a; (void)p; }
来自C,我预计这两个测试用例都需要一个转换来编译.是否有任何理由为什么任何一个方案将是标准合法的?或者,即使通过明确地使用-std = c11而不是-std = gnu11来禁用娱乐GNU C扩展名,支持此代码风格的至少有重要的历史原因?
解决方法
编译器标志(gcc和clang)要求检查严格的标准一致性并拒绝编译不合格的代码是-pedantic-errors:
$gcc -std=c11 -pedantic-errors x.c x.c: In function ‘main’: x.c:3:15: error: initialization from incompatible pointer type [-Wincompatible-pointer-types] double* p = &a; ^
铛:
$clang -std=c11 -pedantic-errors x.c x.c:3:11: error: incompatible pointer types initializing 'double *' with an expression of type 'int *' [-Werror,-Wincompatible-pointer-types] double* p = &a; ^ ~~ 1 error generated.