【发布时间】:2011-10-25 08:19:58
【问题描述】:
我正在使用 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)。 谁能看出区别?
【问题讨论】:
-
ASSERT_EQ是什么?它可能是进行促销或其他一些讨厌的事情。 ideone.com/WxyUc -
@R.MartinhoFernandes:它来自 google gtest 框架。
-
强制转换为无符号和右移都发生在被传递到
ASSERT_EQ之前,但我想它可以定义为ASSERT_EQ(x) foo((int)x)或等效... -
根据优化级别,一个可能的区别是
(unsigned long)(0xffffffff) >> (4*8)已被编译器评估为 0 作为编译时常量表达式,而address >> (4*8)已被不同地翻译,可能是基于相当于x >> y->x >> (y & 0x1F)的规则(我以前见过这种效果,不记得在哪里,与带有 5 位立即操作数的移位指令有关),或者可能通过几个步骤它的 UB-ness 导致它被完全删除。无论哪种方式,它都没有效果,留下实际值 4294967295。 -
我的意思是,它不需要被奇怪的符号扩展,它只需要没有转移。