gpt4 book ai didi

c++ - 移位和屏蔽 32 位值时 uint64_t 的未定义高位

转载 作者:行者123 更新时间:2023-11-30 16:46:10 25 4
gpt4 key购买 nike

我在一个看似无害的函数中存在一些未定义的行为,该函数正在解析缓冲区中的 double 值。我将 double 分为两半,因为我相当确定语言标准规定移位 char 值仅在 32 位上下文中有效。

inline double ReadLittleEndianDouble( const unsigned char *buf )
{
uint64_t lo = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
uint64_t hi = (buf[7] << 24) | (buf[6] << 16) | (buf[5] << 8) | buf[4];
uint64_t val = (hi << 32) | lo;
return *(double*)&val;
}

由于我将 32 位值存储到 64 位变量 lohi 中,因此我合理地期望这些变量的高位 32 位将始终为0x00000000。但有时它们包含 0xffffffff 或其他非零垃圾。

修复方法是像这样屏蔽它:

uint64_t val = ((hi & 0xffffffffULL) << 32) | (lo & 0xffffffffULL);

或者,如果我在作业期间屏蔽,它似乎会起作用:

uint64_t lo = ((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]) & 0xffffffff;
uint64_t hi = ((buf[7] << 24) | (buf[6] << 16) | (buf[5] << 8) | buf[4]) & 0xffffffff;

我想知道为什么这是必要的。我能想到的解释是,我的编译器直接在 64 位寄存器上对 lohi 进行所有移位和组合,并且我可能期望未定义的行为如果是这种情况,则为高位 32 位。

有人可以证实我的怀疑或以其他方式解释这里发生的事情,并评论我的两个解决方案中哪一个(如果有)更可取吗?

最佳答案

如果您尝试移动charunsigned char,您就会受到标准整数提升的支配。在尝试改变这些值之前,您最好自己转换这些值。如果这样做,则不必将下半部分和上半部分分开。

inline double ReadLittleEndianDouble( const unsigned char *buf )
{
uint64_t val = ((uint64_t)buf[7] << 56) | ((uint64_t)buf[6] << 48) | ((uint64_t)buf[5] << 40) | ((uint64_t)buf[4] << 32) |
((uint64_t)buf[3] << 24) | ((uint64_t)buf[2] << 16) | ((uint64_t)buf[1] << 8) | (uint64_t)buf[0];
return *(double*)&val;
}

仅当 CPU 是大端字节序或者缓冲区可能未针对 CPU 架构正确对齐时,所有这些都是必要的,否则您可以大大简化它:

    return *(double*)buf;

关于c++ - 移位和屏蔽 32 位值时 uint64_t 的未定义高位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43860858/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com