指针分配不兼容的技术合法性

前端之家收集整理的这篇文章主要介绍了指针分配不兼容的技术合法性前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
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.

在野外的典型C代码的一个重要的比例(至少)是不合规的,所以这样的语义错误会导致大多数C程序和库无法编译.

猜你在找的C&C++相关文章