我正在使用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 )。有人能看出其中的区别吗?
发布于 2011-10-25 16:27:57
将大于或等于左操作数的位数大小的值移位是未定义的行为(§5.8?1)。(我假设unsigned long
距离您的注释有32位,如果您考虑符号扩展,那么0xfffffff是预期的结果。)
尽管如此,可能是ASSERT_EQ
所做的某些事情导致了这种差异,因为它在GCC 4.5 with good old assert
上运行得很好。
发布于 2011-10-25 16:28:23
我认为这一切都归因于未定义的行为。我认为在按位移位中,如果右操作数大于或等于左操作数中的位数,则结果是未定义的。
发布于 2011-10-25 16:29:05
如果unsigned long
是32位,则将其移位32位的行为是未定义的。引用C++ 2003标准:
如果右操作数为负,或者大于或等于提升的左操作数的位数长度,则行为未定义。
显然,编译时和运行时的求值方式是不同的--这是完全有效的,只要它们在定义的情况下产生相同的结果。
(如果系统上的unsigned long
大于32位,则不适用。)
https://stackoverflow.com/questions/7886504
复制相似问题