我以为我在this answer中发现了类似的东西,但在这种情况下,他们没有将表达式的结果赋给变量。在我的情况下,我正在分配它,但表达式的bitshift部分没有效果。
unsigned leftmost1 = ((~0)>>20);
printf("leftmost1 %u\n", leftmost1);
返回
leftmost1 4294967295
尽管
unsigned leftmost1 = ~0;
leftmost1 = leftmost1 >> 20;
printf("leftmost1 %u\n", leftmost1);
给我
leftmost1 4095
我希望将逻辑分成两行没有影响,为什么结果不同?
答案 0 :(得分:6)
在第一种情况下,您正在进行签名的右移,因为~0
会产生签名值。签名右移的确切行为是实现定义的,但是大多数平台(包括你的平台)都会扩展符号位,因此对于“全部”的输入,移位是无操作。
在第二种情况下,您正在执行无符号右移,因为leftmost1
是unsigned
值。所以你从左边移动了零。
如果你想在没有中间任务的情况下进行无符号移位,你可以这样做:
(~0u) >> 20
u
后缀表示无符号文字。
答案 1 :(得分:3)
~0
是int
。所以你的第一段代码不等于第二段,它相当于
int tmp = ~0;
tmp = tmp >> 20;
unsigned leftmost1 = tmp;
当你右移一个负数时,你会看到符号扩展的结果。
答案 2 :(得分:2)
尝试像这样投射。 〜0被提升为 int,这是签名所以当你转移时它带有符号位
unsigned leftmost1 = ((unsigned)(~0)>>20);
printf("leftmost1 %u\n", leftmost1);
答案 3 :(得分:2)
0
的类型为int
。典型的双补机上~0
为-1
。右移负数具有实现定义的结果,但常见的选择是移入1
位,-1
使数字保持不变(即-1 >> anything
为{{1}再次)。
您可以通过编写-1
(类型为0u
的文字)来解决此问题。这会强制操作在unsigned int
中完成,如第二个示例所示:
unsigned int
此行等同于unsigned leftmost1 = ~0;
,它隐式地将-1(带符号的int)转换为unsigned leftmost1 = -1
。然后,以下操作(UINT_MAX
)使用无符号算术。