微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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程序和库无法编译.

原文地址:https://www.jb51.cc/c/113511.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐