紧跟a specific problem,自我回答并对其发表评论,我想了解它是否是一个正确的解决方案,解决方法/黑客攻击或者只是错误。
具体来说,我改写了代码:
T x = ...;
if (*reinterpret_cast <int*> (&x) == 0)
...
如:
T x = ...;
if (*reinterpret_cast <volatile int*> (&x) == 0)
...
指针的volatile
限定符。
我们假设在我的情况下将T
视为int
是有道理的。这是通过volatile
引用解决指针别名问题吗?
作为参考,来自规范:
[注意:volatile是一个提示,以避免攻击性 涉及对象的优化,因为对象的值可能 通过实现无法检测的方式进行更改。见1.9 详细的语义。通常,volatile的语义是有意的 在C ++中与在C中相同。 - 结束语]
编辑:
上述代码确实至少在GCC 4.5上解决了我的问题。
答案 0 :(得分:15)
Volatile无法帮助您避免未定义的行为。所以,如果GCC对你有用,那就很幸运了。
我们假设T是POD。然后,正确的方法是
T x = …;
int i;
memcpy(&i,&x,sizeof i);
if (i==0)
…
有!没有严格的别名问题和没有内存对齐问题。 GCC甚至将memcpy作为内部函数处理(在这种情况下不插入函数调用)。
答案 1 :(得分:-4)
Volatile无法帮助您避免未定义的行为。
嗯,关于volatile
的任何内容在标准中都有些不清楚。我大多同意你的回答,但现在我想稍微不同意。
为了理解volatile
的含义,大多数人都不清楚标准,特别是一些编译器编写者。最好考虑一下:
使用volatile
时(仅当时),C / C ++几乎是高级程序集。
当写入volatile
左值时,编译器将发出一个STORE或多个STORE(如果一个不够)(volatile
并不意味着原子)。
当写入volatile
左值时,编译器将发出一个LOAD,如果还不够,则发出多个LOAD。
当然,如果没有明确的LOAD或STORE,编译器只会发出暗示LOAD或STORE的指令。
sellibitze提供了最佳解决方案:使用memcpy
进行位重新解释。
但如果所有对内存区域的访问都是使用volatile
左值完成的,则非常清楚严格的别名规则不适用。这是你问题的答案。