【发布时间】:2015-08-12 14:48:00
【问题描述】:
我有一个关于严格别名规则、联合和标准的问题。假设我们有以下代码:
#include <stdio.h>
union
{
int f1;
short f2;
} u = {0x1};
int * a = &u.f1;
short * b = &u.f2;
int main()
{
u.f1 = 1;
*a += 1;
u.f2 = 2;
*b *= 2;
printf( "%d %hd\n", *a, *b);
return 0;
}
现在让我们看看它是如何工作的:
$ gcc-5.1.0-x86_64 t.c -O3 -Wall && ./a.out
2 4
$ gcc-5.1.0-x86_64 t.c -O3 -Wall -fno-strict-aliasing && ./a.out
4 4
我们可以看到,严格别名会破坏依赖关系。此外,它似乎是一个正确的代码,没有违反严格的别名规则。
- 事实证明,与联合字段的情况相比,位于该地址的对象与所有类型的联合成员兼容吗?
- 如果 1 为真,编译器应该如何处理指向联合成员的指针? 允许这样的编译器行为是标准中的问题吗?如果不是 - 为什么?
- 一般来说,编译器的不同行为与正确的代码在任何情况下都是不可接受的。所以它似乎也是一个编译器错误(特别是如果将地址带到联合字段将在函数内部,SA 不会破坏依赖关系)。
【问题讨论】:
-
不,这不是正确的代码。严格的别名是标准的要求,而不是编译器。 gcc 有礼貌地为损坏的代码禁用此功能。
-
@Olaf:有些实现定义了上述代码的行为,有些则没有。仅限于支持超出标准要求的行为的编译器(即最有用的程序)的代码可能不是完全可移植的,但这并不意味着它们在任何意义上都是“损坏的”。相比之下,gcc 在许多情况下的行为(尽管不是上述情况)会被彻底破坏,除非它(1)以一种会使标准变得毫无意义的方式应用“一个程序规则”,或者(2)证明它符合需要
-fno-strict-aliasing或-O0。
标签: c standards strict-aliasing