关于类型双关语的问题:为什么这段代码会破坏严格的别名规则:
int main()
{
int a = 1;
short j;
printf("%i\n", j = *((short*)&a));
return 0;
}
而这不是:
int main()
{
int a = 1;
short j;
int *p;
p=&a;
printf("%i\n", j = *((short*)p));
return 0;
}
按gcc -fstrict-aliasing
建造。
谢谢!
答案 0 :(得分:11)
他们都违反了strict aliasing rule,我将引用我的answer here来说明(强调我的前进):
在代码违反了strict aliasing rules,通过不同类型的指针访问对象是非法的,尽管允许通过char *进行访问。允许编译器假设不同类型的指针不指向相同的存储器并相应地进行优化。
gcc
here的文档中, -Wstrict-aliasing=n
稍微详细一点,其中说:
此选项仅在-fstrict-aliasing处于活动状态时处于活动状态。它会警告可能会破坏编译器用于优化的严格别名规则的代码。 更高的级别对应更高的准确性(更少的误报)。更高的级别也相应于更多的努力,类似于-O的工作方式。 -Wstrict-aliasing相当于-Wstrict-aliasing = 3。
并描述每个级别如下:
等级1:最具攻击性,快速,最不准确。可能有用的时候 更高级别不会警告但-fstrict-aliasing仍会破坏代码, 因为它的假阴性很少。但是,它有很多错误 阳性。警告可能的所有指针转换 不兼容的类型,即使从未解除引用。在前端运行 仅
第2级:积极,快速,不太精确。可能还有很多错误 积极性(尽管不是1级),而且很少有误报 (但可能超过1级)。与1级不同,它仅在何时发出警告 一个地址。警告不完整的类型。在前面跑 仅结束。
等级3(-Wstrict-aliasing的默认值):应该有很少的错误 积极的,很少的假阴性。比1或2级略慢 何时启用优化。 照顾常见的双关语+解除引用 前端的模式:
*(int*)&some_float
。如果是优化 启用后,它还会在后端运行,处理多个 声明案例使用流敏感点 - 信息。只是警告 当转换的指针被解除引用时。不警告 不完整的类型。
因此无法保证捕获所有实例,不同级别具有不同的准确度。
通常情况下,您正在寻找的效果可以通过联合使用类型惩罚来完成,我在上面的链接答案和gcc explicitly supports中介绍了这一点。