【问题标题】:Does passing to a function two pointers pointed to members of the same union violate the strict aliasing rule? [duplicate]将两个指向同一个联合成员的指针传递给函数是否违反了严格的别名规则? [复制]
【发布时间】:2021-09-01 09:55:04
【问题描述】:

注意:学习严格的别名规则。请耐心等待。

代码示例(t935.c):

#include <stdio.h>

int f(int* pi, double* pd)
{
    *pi = 13;
    *pd = 7E-323;
    return *pi;
}

int main(void)
{
    union { int i; double d; } u;
    printf("%d\n", f(&u.i, &u.d));
    return 0;
}

调用:

$ gcc t935.c -Wall -Wextra -std=c11 -pedantic  && ./a.exe
14

$ gcc t935.c -Wall -Wextra -std=c11 -pedantic -O2 && ./a.exe
13

$ gcc t935.c -Wall -Wextra -std=c11 -pedantic -O2 -fno-strict-aliasing && ./a.exe
14

问题:将两个指向同一个联合成员的指针传递给函数是否违反了严格的别名规则?

问题来自Unions and type-punning

UPD20210901

如果在全局范围内定义联合类型会发生什么?

对于“union u is defined in global scope”(实际上是 file 范围)情况,gcc 和 clang 显示的结果与上面报告的 gcc 相同。

【问题讨论】:

  • 是的。 union 在f() 的体内是不可见的,如果union 类型是在全局范围内定义的会发生什么?
  • @tstanisl 不确定工会的范围为何或如何对此有任何影响。该函数只看到两个指针,并分别使用它们:它们指向“相同”的地方是无关紧要的,不是吗?
  • 标准中有一个关于联合可见性和严格别名规则的微妙之处,请参阅gcc.gnu.org/bugzilla/show_bug.cgi?id=65892
  • @NateEldredge 感谢您提供信息!有趣。

标签: c pointers constraints c11 strict-aliasing


【解决方案1】:

这是 C 标准中的一个缺陷。见Defect Report 236

6.5 7 中的别名规则旨在允许编译器假定指向不满足规则的两种类型的指针引用“不同”对象,但该规则未能充分提供联合成员(而且,根据缺陷报告,动态分配内存中的对象)。获取两个联合成员的地址可能会产生指向两种类型的指针,这些类型可能不会根据别名规则进行别名但引用相同的内存。因此,C 标准在这方面被打破了,C 委员会也没有纠正这个问题。

【讨论】:

  • 有趣....
  • 不幸的是,虽然 DR#236 对给出的特定代码段得出了正确的结论,但它这样做是基于一个荒谬的基本原理,将实现定义的行为和未定义的行为行为视为等效的。示例 2 应被视为 UB,因为可用于访问 union tag 的类型列表不包括 intdouble。显然,编译器应该允许这种类型的左值在编译器可以看到int*double* 派生自类型对象的上下文中访问union tag 类型的对象的可能性......
  • union tag,或仅通过int* 或仅通过double* 访问对象的情况,但编译器何时会注意到这种指针派生的问题,或者它的范围有多广或多窄绘制了别名很重要的上下文,被视为实现问题的质量。 “有效类型”规则实际上是对 DR236 中给出的荒谬基本原理的编纂。
猜你喜欢
  • 2016-10-09
  • 2014-07-26
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多