在文字与变量上签名扩展

时间:2011-10-25 08:19:59

标签: c++ bit-shift

我正在使用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)。 有人能发现差异吗?

4 个答案:

答案 0 :(得分:5)

移位大于或等于左操作数(§5.8¶1)的位大小的值是未定义的行为。 (我假设unsigned long是关于0xfffffff的评论中的32位,如果您考虑使用符号扩展,则为预期结果。)

尽管如此,ASSERT_EQ可能会导致差异,因为它可以在GCC 4.5 with good old assert上正常工作。

答案 1 :(得分:3)

我认为这完全取决于未定义的行为。我相信在按位移位时,如果右操作数大于或等于左操作数中的位数,则结果是不确定的。

答案 2 :(得分:2)

如果unsigned long是32位,则将其移位32位的行为是不确定的。引用C ++ 2003标准:

  

如果右操作数为负数或更大,则行为未定义   大于或等于提升的左操作数的位数。

显然,编译时和运行时评估是以不同的方式完成的 - 只要它们在定义的情况下产生相同的结果,它就完全有效。

(如果unsigned long在系统上超过32位,则不适用。)

答案 3 :(得分:0)

这些测试pass on gcc-4.3.4都是普通的assert