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