关于gcc中类型惩罚的编译器警告

时间:2014-09-09 13:38:03

标签: c++ gcc types

我有一个大型程序,其中包含大量

形式的片段
float t = amplitudes->read(current_element);
    if ( *((uint32_t * ) &t) == 0xsomereservedvalue)
         do_something
     else
          do_something_else

这与gcc 3.4.x编译没有警告。使用-Wtrict-aliasing = 2编译仍然没有警告。我最近尝试使用gcc4.4进行编译,并获得了大量关于类型惩罚引用的警告。有人能告诉我有没有合理的情况下这种代码会失败?据我所知,如果优化排列的东西可以在另一行代码读取后从寄存器写回来,那么输入punning只是一个潜在的问题,因为我们在这里返回一个函数根本无法发生。我在这里遗漏了什么,或者gcc有点脑死亡?

2 个答案:

答案 0 :(得分:1)

当然它警告说。我刚刚检查了gcc 4.8.2它也发出了警告。想象一下,目标机器的浮点大小是16位,你试图在数据绑定后读取32位。这是UB。

btw在这种情况下,我不同意reinterpret_cast的用法。 reinterpret_cast唯一有用的方法是*(reinterpret_cast<char *>(&t)),即使*(reinterpret_cast<unsigned *>(&t))仍会破坏别名规则,您也会得到相同的警告。这是因为编译器只在C ++中知道char是最小的,因此每种类型都可以转换为它。

GCC有一个属性来告诉给定类型可能是别名。它也不是那么容易使用。

unsigned * __attribute__ ((__may_alias__)) pu = (unsigned *) &t;
if (*pu == 0xsomereservedvalue)
  do_something ();
else
  do_something_else ();

但这里的事情至少是有道理的。我们要求使用别名指针。成本:代码现在不可移植。

因此,经过所有考虑后,如果您确定自己知道自己在做什么,我建议您只提供-fno-strict-aliasing选项。

答案 1 :(得分:1)

“解除引用类型 - 惩罚指针将破坏严格别名”告诉您编译器可能正在进行可能会破坏您的代码的优化。

这可能发生的原因是允许编译器(根据语言规范)假设您只访问具有自己的类型或char类型的数组。

为了保证正确性,必须在禁用严格别名的情况下使用memcpy进行打字或构建。 (工会有点不清楚)

请查看here,了解有关严格别名的其他详细信息。