8

特定问题、自我回答和评论之后,我想了解它是否是正确的解决方案、解决方法/黑客或完全错误。

具体来说,我重写了代码:

T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
  ...

作为:

T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
  ...

带有volatile指针的限定符。

让我们假设在我的情况下对待Tint有道理的。这种通过volatile引用访问是否解决了指针别名问题?

作为参考,来自规范:

[注意: volatile 是对实现的提示,以避免涉及对象的激进优化,因为对象的值可能会通过实现无法检测到的方式进行更改。详细语义见 1.9。一般来说,volatile 的语义在 C++ 中与在 C 中的语义相同。 — 尾注]

编辑:

上面的代码至少在 GCC 4.5 上确实解决了我的问题。

4

2 回答 2

17

Volatile 无法帮助您避免此处未定义的行为。因此,如果它适用于 GCC,那是幸运的。

假设 T 是一个 POD。然后,正确的方法是

T x = …;
int i;
memcpy(&i,&x,sizeof i);
if (i==0)
  …

那里!没有严格的别名问题,也没有内存对齐问题。GCC 甚至将 memcpy 作为内在函数处理(在这种情况下没有插入函数调用)。

于 2010-06-05T19:59:32.493 回答
-7

Volatile 无法帮助您避免此处未定义的行为。

好吧,volatile标准中有关的任何内容都有些不清楚。我基本上同意你的回答,但现在我想稍微不同意。

为了理解什么volatile意思,对于大多数人来说,标准并不清楚,尤其是一些编译器编写者。最好这样想: 在使用时volatile(并且仅在使用时),C/C++ 几乎是高级程序集

写入volatile左值时,编译器将发出一个 STORE,或者如果一个 STORE 不够(volatile并不意味着原子),则发出多个 STORE。

写入volatile左值时,编译器将发出一个 LOAD,如果一个不够,编译器将发出多个 LOAD。

当然,在没有明确的 LOAD 或 STORE 的情况下,编译器只会发出暗示 LOAD 或 STORE 的指令。

sellibitze 给出了最好的解决方案:用于memcpy位重新解释。

但是,如果对内存区域的所有访问都是使用volatile左值完成的,那么很明显严格的别名规则不适用。这是您的问题的答案。

于 2012-07-15T00:35:56.567 回答