文字与变量的符号扩展
我正在使用 gcc 4.4.5,并且在理解普通简单无符号值上的右移运算符时遇到一些困难...
此测试
ASSERT_EQ( 0u, (unsigned long)(0xffffffff) >> (4*8) );
通过。
该测试
unsigned long address = 0xffffffff;
ASSERT_EQ( 0u, address >> (4*8) );
失败:
Value of: address >> (4*8)
Actual: 4294967295
Expected: 0u
变量似乎被视为有符号值,因此导致符号扩展。 (0xffffffff 十进制为 4294967295)。 有人能看出其中的区别吗?
I'm working with gcc 4.4.5, and have some difficulties in understanding the right shift operator on plain simple unsigned values...
This test
ASSERT_EQ( 0u, (unsigned long)(0xffffffff) >> (4*8) );
passes.
This test
unsigned long address = 0xffffffff;
ASSERT_EQ( 0u, address >> (4*8) );
fails:
Value of: address >> (4*8)
Actual: 4294967295
Expected: 0u
It seems that the variable is treated like a signed value, and thus results in sign-extension. (0xffffffff is 4294967295 in decimal).
Can anyone spot the difference?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
移位大于或等于左操作数位大小的值是未定义的行为 (§5.8¶1)。 (如果您考虑符号扩展,我假设
unsigned long
是 32 位,来自您对 0xfffffff 的评论,这是预期的结果。)不过,
ASSERT_EQ
可能会做一些事情导致差异,因为它在 GCC 4.5 和旧的assert
上运行良好。It is undefined behaviour to shift a value greater than or equal the size in bits of the left operand (§5.8¶1). (I assume
unsigned long
is 32 bits from your comments about 0xfffffff being the expected result if you consider sign extension.)Still, there's probably something that
ASSERT_EQ
does that causes the difference, as it works fine on GCC 4.5 with good oldassert
.我认为这都是由于未定义的行为造成的。我相信,在按位移位中,如果右操作数大于或等于左操作数中的位数,则结果是未定义的。
I think that this is all down to undefined behaviour. I believe that in bitwise shifts the results are undefined if the right operand is greater than or equal to the number of bits in the left operand.
如果
unsigned long
是32位,那么将其移位32位的行为是未定义的。引用C++ 2003标准:显然,编译时和运行时评估的方式不同——只要它们在定义的情况下产生相同的结果,这是完全有效的。
(如果您系统上的
unsigned long
宽度超过 32 位,则这不适用。)If
unsigned long
is 32 bits, then the behavior of shifting it by 32 bits is undefined. Quoting the C++ 2003 standard:Apparently the compile-time and run-time evaluations are done differently -- which is perfectly valid as long as they yield the same results in cases where it's defined.
(If
unsigned long
is wider than 32 bits on your system, this doesn't apply.)这两个测试都使用普通的旧
assert
来通过 gcc-4.3.4。Both those tests pass on gcc-4.3.4 with plain old
assert
.