【发布时间】:2015-03-30 03:49:12
【问题描述】:
我读得越多,我就越困惑。
相关问题的最后一个问题与我的问题最接近,但我对所有关于对象生命周期的词感到困惑,尤其是 - 是否可以只阅读。
直奔主题。如果我错了,请纠正我。
这很好,gcc 不发出警告,我正在尝试“通过char* 读取类型T (uint32_t)”:
uint32_t num = 0x01020304;
char* buff = reinterpret_cast< char* >( &num );
但这很“糟糕”(也会发出警告),我正在尝试“反过来”:
char buff[ 4 ] = { 0x1, 0x2, 0x3, 0x4 };
uint32_t num = *reinterpret_cast< uint32_t* >( buff );
第二个与第一个有何不同,尤其是在我们讨论重新排序指令(用于优化)时?另外,添加const 不会以任何方式改变这种情况。
或者这只是一条直截了当的规则,明确规定:“这可以在一个方向上完成,但不能在另一个方向上完成”? 我在标准中找不到任何相关内容(特别是在 C++11 标准中搜索过)。
这对于 C 和 C++ 是否相同(当我阅读评论时,暗示这两种语言的情况不同)?
我使用union 来“解决”这个问题,这似乎仍然是NOT 100% OK,因为标准不能保证它(其中指出,我只能依赖该值, 最后修改在union)。
所以,读了很多之后,我现在更加困惑了。我猜只有memcpy 是“好”的解决方案?
相关问题:
- What is the strict aliasing rule?
- "dereferencing type-punned pointer will break strict-aliasing rules" warning
- Do I understand C/C++ strict-aliasing correctly?
- Strict aliasing rule and 'char *' pointers
编辑
实际情况:我有一个第三方库(http://www.fastcrypto.org/),它计算 UMAC,返回值在char[ 4 ]。然后我需要将其转换为uint32_t。而且,顺便说一句,lib 经常使用((UINT32 *)pc->nonce)[0] = ((UINT32 *)nonce)[0] 之类的东西。无论如何。
另外,我在问什么是对的,什么是错的,以及为什么。不仅是重新排序、优化等(有趣的是-O0 没有警告,只有-O2)。
请注意:我知道大/小端的情况。这里不是这样。我真的很想忽略这里的字节序。 “严格的别名规则”听起来很严肃,比错误的字节序严重得多。我的意思是——比如访问/修改不应该被触及的内存; 任何种 UB。
引用标准(C 和 C++)将不胜感激。我找不到任何关于别名规则或任何相关内容的信息。
【问题讨论】:
-
buff 甚至可能没有适当对齐...
-
“第二个与第一个有何不同”,我假设您的意思是严格考虑寻址和别名,因为该代码是不可移植的。即使对齐不是问题,
num是后者的值也不能保证与前者的初始值num相等,除非您在 bigE 平台上。 -
@WhozCraig - 是的,我知道大/小端。是的,我在问它是否便携和可靠,如果不是 - 为什么(我的意思是,我不仅对代码重新排序感兴趣)。
-
我明白了。这是一个很好的问题,我只是不想让随便的新手看到这一点,并认为这是解决他们 raw-bytes-to-
uint32困境的灵丹妙药。顺便提一下你的问题。由于您对此缺乏研究,任何理智的人都不会投反对票。 -
规则以“如果程序试图通过非下列类型之一的左值访问对象的存储值,则行为未定义:[...]”开始。在您的第一种情况下,“对象”是
uint32_t,您通过char类型的glvalue 访问它,这是允许的;在第二种情况下,“对象”是char或chars 的数组,您通过uint32_t类型的glvalue 访问它,这不是任何允许的类型。
标签: c++ c reinterpret-cast strict-aliasing