再一次:严格的别名规则和char*

Kir*_*rov 13 c c++ strict-aliasing reinterpret-cast

我读的越多,我就越困惑.

相关问题的最后一个问题与我的问题最接近,但是我对所有关于对象生命周期的问题感到困惑,尤其是 - 只读或不读.


直截了当.如我错了请纠正我.

这很好,gcc没有发出警告,我正试图" 通过" 读取类型T(uint32_t)char*:

uint32_t num = 0x01020304;
char* buff = reinterpret_cast< char* >( &num );
Run Code Online (Sandbox Code Playgroud)

但这是"坏"(也是一个警告),我正在尝试"反过来":

char buff[ 4 ] = { 0x1, 0x2, 0x3, 0x4 };
uint32_t num = *reinterpret_cast< uint32_t* >( buff );
Run Code Online (Sandbox Code Playgroud)

第二个如何与第一个不同,特别是当我们谈论重新排序指令(用于优化)时?另外,添加const不会以任何方式改变这种情况.

或者这只是一条直接规则,它明确指出:"这可以在一个方向完成,但在另一个方向不能完成"?我在标准中找不到任何相关内容(特别是在C++ 11标准中搜索过).

C和C++是否相同(因为我读了一条评论,暗示它与2种语言不同)?


我曾经union"解决"这个问题,但仍然看起来并非 100%正常,因为标准无法保证(这表明我只能依赖于最后一次修改的值union).

所以,经过大量阅读,我现在更加困惑.我想只是memcpy"好"的解决方案?


相关问题:


编辑
现实世界的情况:我有一个第三方库(http://www.fastcrypto.org/),它计算UMAC并返回值char[ 4 ].然后我需要将其转换为uint32_t.而且,顺便说一句,lib使用的东西((UINT32 *)pc->nonce)[0] = ((UINT32 *)nonce)[0]很多.无论如何.

另外,我问的是什么是对的,什么是错的以及为什么.不仅仅是关于重新排序,优化等等(有趣的是,-O0没有警告,只有-O2).

请注意:我知道大/小端情况.情况并非如此.我真的想忽略这里的字节序."严格的别名规则"听起来像是非常严肃的事情,远比错误的字节序严重得多.我的意思是 - 就像访问/修改内存一样,不应该被触及; 任何一种UB都可以.

标准(C和C++)的引用将非常感激.我找不到任何关于别名规则或任何相关的内容.

dav*_*mac 9

第二个如何与第一个不同,特别是当我们谈论重新排序指令(用于优化)时?

问题在于编译器使用规则来确定是否允许这样的优化.在第二种情况下,您尝试char[]通过不兼容的指针类型读取对象,这是未定义的行为; 因此,编译器可能会重新排序读取和写入(或执行您可能不期望的任何其他操作).

尽管看起来不自然,但你真的不得不考虑你认为编译器可能如何优化,并且只是遵守规则.

或者这只是一条直接规则,它明确指出:"这可以在一个方向完成,但在另一个方向不能完成"?我在标准中找不到任何相关内容(特别是在C++ 11标准中搜索过).

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf第3.10章第10段.

在C99中,我认为也是C11,它是6.5第7段.

C和C++都允许通过char *(或者特别是类型的左值char)访问任何对象类型.它们不允许char通过任意类型访问对象.所以是的,规则是一种"单向"规则.

我使用union来"解决"这个问题,这看起来仍然不是100%正常,因为标准不能保证(这表明我只能依赖于最后修改的值).

尽管该标准的措辞非常模糊,但在C99(及以后)中,很明显(至少从C99 TC3开始)意图是允许通过联合进行类型惩罚.但是,您必须通过联合执行所有访问(特别是您不能仅仅为了类型惩罚而'为了存在而构建联合').

返回的值在char [4]中.然后我需要将其转换为uint32_t

只需使用memcpy或手动将字节移动到正确的位置,以防字节排序成为问题.好的编译器无论如何都可以优化它(是的,甚至是调用memcpy).


归档时间:

查看次数:

812 次

最近记录:

10 年,10 月 前