【发布时间】:2018-02-25 01:11:44
【问题描述】:
我想将 0xff 左移 3 个字节并将其存储在 uint64_t 中,它应该可以这样工作:
uint64_t temp = 0xff << 24;
这会产生0xffffffffff000000 的值,这绝对不是预期的0xff000000。
但是,如果我将其移动少于 3 个字节,则会得到正确答案。
此外,尝试将 0x01 左移 3 个字节确实有效。
这是我的输出:
0xff shifted by 0 bytes: 0xff
0x01 shifted by 0 bytes: 0x1
0xff shifted by 1 bytes: 0xff00
0x01 shifted by 1 bytes: 0x100
0xff shifted by 2 bytes: 0xff0000
0x01 shifted by 2 bytes: 0x10000
0xff shifted by 3 bytes: 0xffffffffff000000
0x01 shifted by 3 bytes: 0x1000000
通过一些实验,每个 uint64_t 左移最多 3 位,直到 0x7f,产生 0x7f000000。 0x80 产生 0xffffffff80000000。
有人对这种奇怪的行为有解释吗? 0xff000000 肯定落在 uint64_t 的 264 - 1 限制内。
【问题讨论】:
-
0xff是一个int,通常是一个 32 位整数。所以0xff << 24正在对 32 位整数进行数学运算,而不是在uint64_ts 上。所以最左边的1位被视为符号位,所以当我们将宽度扩展为64位整数时,我们将所有新位设置为1,这使得当我们转换为时所有fs一个无符号整数 -
“奇怪”如“我不明白”?这种行为的原因是所有这些常量的类型为
int。要获得您正在寻找的行为,请确保它们是 64 位宽,或者通过将它们显式写入无符号 long long 值(例如,0xffULL)或强制转换为std::uint64_t。 -
试试
uint64_t temp = 0xffu << 24;或uint64_t temp = 0xfful << 24; -
@gurka 最好建议
uint64_t(0xff) << 24为long不必是 64 位宽。 -
@gurka --
unsigned只需 16 位宽,unsigned long32 位宽。它们可能在您的编译器中更宽,但要确保 64 位,请使用 64 位类型,unsigned long long(至少为 64 位)或std::uint64_t,如果存在,则正好64 位宽。
标签: c++ bit-manipulation bit-shift