为什么将0xff移位 24 位会导致值不正确?
Why does shifting 0xff left by 24 bits result in an incorrect value?
我想将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限制。
有人对这种奇怪的行为有解释吗?
是的,操作类型始终取决于操作数类型,而从不依赖于结果类型:
double r = 1.0 / 2.0;
// double divided by double and result double assigned to r
// r == 0.5
double r = 1.0 / 2;
// 2 converted to double, double divided by double and result double assigned to r
// r == 0.5
double r = 1 / 2;
// int divided by int, result int converted to double and assigned to r
// r == 0.0
当你理解并反思这一点时,你就不会再犯这个错误了。
我怀疑该行为取决于编译器,但我看到了同样的事情。
修复很简单。 请务必在执行班次之前将0xff转换为uint64_t类型。 这样,编译器将把它作为正确的类型来处理。
uint64_t temp = uint64_t(0xff) << 24
左移会创建一个负数(32 位),然后将其填充为 64 位。
尝试
0xff << 24LL;
让我们把你的问题分成两部分。第一个是移位操作,另一个是转换为uint64_t
。
就左移而言,您正在 32 位(或更小)体系结构上调用未定义的行为。正如其他人所提到的,操作数是int
.具有给定值的 32 位int
将0x000000ff
。请注意,这是一个有符号的数字,所以最左边的位是符号。根据标准,如果移位影响符号位,则结果是不确定的。它取决于实现的突发奇想,它随时可能发生变化,如果编译器在编译时识别它,它甚至可以完全优化。后者是不现实的,但实际上是允许的。虽然你永远不应该依赖这种形式的代码,但这实际上并不是让你困惑的行为的根源。
现在,第二部分。左移操作的未定义结果必须转换为uint64_t
。有符号到无符号整数转换的标准状态:
如果目标类型是无符号的,则结果值是等于源值模 2n 的最小无符号值,其中 n 是用于表示目标类型的位数。
也就是说,根据目标类型是宽还是窄,有符号整数是符号扩展的[脚注 1],或者截断的和无符号的整数分别是零扩展或截断。
脚注澄清了符号扩展仅适用于二进制补码表示,目前在具有C++编译器的每个平台上都使用。
符号扩展意味着目标变量上符号位的剩余所有内容都将用符号位填充,这会在结果中产生所有f
。正如您所指出的,您可以在不发生这种情况的情况下将0x7f
左移 3 个字节,那是因为0x7f=0b01111111
.移位后,你会得到0x7f000000
哪个是最大的有符号整数,即不影响符号位的最大数字。因此,在转换中,延长了0
。
将左操作数转换为足够大的类型可以解决此问题。
uint64_t temp = uint64_t(0xff) << 24
- 使用2个键的cpp-stl::优先级队列排序不正确
- 正弦级数方程计算不正确
- 我试图制作一个程序,要求用户输入问题和答案,但程序循环不正确
- 密码登录程序将永远循环并显示不正确的结果
- 在C++中返回不正确的楼层函数值
- 形状对象的旋转和缩放不正确C++
- C++ 读取文件读取文件不正确
- 关于类的 Python 文档 - 对C++的引用不正确
- 特征 LLT 模块给出不正确的结果?
- glibcxx STL 在实现 std::valarray::sum() 时是否不正确?
- 如果语句逻辑不正确
- 来自逆 vp 矩阵和相机位置的光线方向不正确
- 不正确的操作数类型 MSVC
- 数组填充了不正确的值
- 我是否不正确地集中了这些字符数组?
- 为什么除非我使用 cout,否则我的值不正确?
- 计算幂级数的数学结果不正确
- 为什么 sizeof 在 C++ 中给出不正确的字节数?
- atoi() 在应用于大型命令行参数时会产生不正确的值
- 为什么将0xff移位 24 位会导致值不正确?