关于类型双关语的问题:为什么这段代码会破坏严格的别名规则:
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
建立。
谢谢!
他们都违反了strict aliasing rule,我将引用我的answer here说(强调我的前进):
代码违反了strict aliasing rules,这使得通过不同类型的指针访问对象是非法的,尽管允许通过char *进行访问。允许编译器假设不同类型的指针不指向相同的存储器并相应地进行优化。
qazxsw poi在qazxsw poi qazxsw poi的文档中有点详细说明:
此选项仅在-fstrict-aliasing处于活动状态时处于活动状态。它会警告可能会破坏编译器用于优化的严格别名规则的代码。更高的级别对应于更高的准确性(更少的误报)。更高的级别也相应于更多的努力,类似于-O的工作方式。 -Wstrict-aliasing相当于-Wstrict-aliasing = 3。
并描述每个级别如下:
- 1级:最具攻击性,快速,最不准确。当更高级别没有警告但-fstrict-aliasing仍然会破坏代码时可能很有用,因为它几乎没有错误的否定。但是,它有许多误报。警告可能不兼容的类型之间的所有指针转换,即使从未解除引用。仅在前端运行。
- 等级2:积极,快速,不太精确。可能仍有许多误报(尽管不是1级),也没有假阴性(但可能超过1级)。与级别1不同,它仅在发出地址时发出警告。警告不完整的类型。仅在前端运行。
- 级别3(-Wstrict-aliasing的默认值):应该具有非常少的误报和很少的误报。启用优化后,比级别1或2略慢。在前端处理常见的双关语+解除引用模式:
gcc
。如果启用了优化,它也会在后端运行,它使用流敏感点来处理多个语句案例。仅在取消引用转换后的指针时发出警告。不警告不完整的类型。
因此不能保证捕获所有实例,不同级别具有不同程度的准确性。
通常情况下,您正在寻找的效果可以使用通过联合的类型惩罚来完成,我将在上面的链接答案和-Wstrict-aliasing=n
中介绍。