文字与变量的符号扩展

发布于 2024-12-11 21:42:16 字数 473 浏览 0 评论 0原文

我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

腹黑女流氓 2024-12-18 21:42:16

移位大于或等于左操作数位大小的值是未定义的行为 (§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 old assert.

空‖城人不在 2024-12-18 21:42:16

我认为这都是由于未定义的行为造成的。我相信,在按位移位中,如果右操作数大于或等于左操作数中的位数,则结果是未定义的。

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.

雅心素梦 2024-12-18 21:42:16

如果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:

The behavior is undefined if the right operand is negative, or greater
than or equal to the length in bits of the promoted left operand.

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.)

〗斷ホ乔殘χμё〖 2024-12-18 21:42:16

这两个测试都使用普通的旧 assert通过 gcc-4.3.4

Both those tests pass on gcc-4.3.4 with plain old assert.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文