将指向同一联合成员的两个指针传递给函数是否违反了严格的别名规则?
注意:学习严格的别名规则。请耐心等待。
代码示例(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 和 type-punning。
UPD20210901
对于“u在全局范围内定义联合”(实际上是文件范围)的情况,gcc 和 clang 显示的结果与上面报告的 gcc 相同。
回答
这是 C 标准中的一个缺陷。参见缺陷报告 236。
6.5 7 中的别名规则旨在允许编译器假定指向不满足规则的两种类型的指针引用“不同”对象,但该规则未能充分提供联合成员(而且,根据缺陷报告,动态分配的内存中的对象)。取两个联合成员的地址可能会产生指向两种类型的指针,根据别名规则可能不会别名但引用相同的内存。因此,C标准在这方面被打破了,C委员会也没有纠正这个问题。