C中的严格别名

关于类型惩罚的问题:为什么这段代码会破坏严格的别名规则:

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构建。

谢谢!

他们都违反了严格的别名规则 ,我将在这里引用我的答案 ( 强调我的前进 ):

代码违反了严格的别名规则 ,这使得通过不同类型的指针访问对象是非法的 ,尽管允许通过char *进行访问。 允许编译器假设不同类型的指针不指向相同的存储器并相应地进行优化。

gcc-Wstrict-aliasing=n的文档中稍微详细一点,其中说:

此选项仅在-fstrict-aliasing处于活动状态时处于活动状态。 它警告可能会破坏编译器用于优化的严格别名规则的代码。 较高的水平对应于较高的准确度(较少的误报) 。 更高的级别也相应于更多的努力,类似于-O的工作方式。 -Wstrict-aliasing相当于-Wstrict-aliasing = 3。

并描述每个级别如下:

  • 1级:最具攻击性,快速,最不准确。 当更高级别没有警告但-fstrict-aliasing仍然会破坏代码时可能很有用,因为它几乎没有错误否定。 但是,它有许多误报。 警告可能不兼容的类型之间的所有指针转换,即使从未解除引用。 仅在前端运行。

  • 第2级:积极,快速,不太精确。 可能仍然有许多误报(尽管不是1级),也没有假阴性(但可能超过1级)。 与级别1不同,它仅在发出地址时发出警告。 警告不完整的类型。 仅在前端运行。

  • 级别3(-Wstrict-aliasing的默认值):应该具有非常少的误报和很少的误报。 启用优化时,比级别1或2略慢。 在前端处理常见的pun + dereference模式: *(int*)&some_float 如果启用了优化,它也会在后端运行,它使用流敏感点来处理多个语句情况。 仅在取消引用转换后的指针时发出警告。 不警告不完整的类型。

因此不能保证捕获所有实例,不同级别具有不同的准确度。

通常,您正在寻找的效果可以通过联合使用类型惩罚来完成,我在上面的链接答案中介绍了gcc明确支持的 。