赋值时的位移位对变量没有影响
Bitshift on assignment has no effect on the variable
我以为我在 this answer 中找到了类似的东西,但在那种情况下,他们没有将表达式的结果分配给变量。在我的例子中,我正在分配它,但表达式的位移位部分没有效果。
unsigned leftmost1 = ((~0)>>20);
printf("leftmost1 %u\n", leftmost1);
Returns
leftmost1 4294967295
鉴于
unsigned leftmost1 = ~0;
leftmost1 = leftmost1 >> 20;
printf("leftmost1 %u\n", leftmost1);
给我
leftmost1 4095
我希望将逻辑分成两行不会有影响,为什么结果不同?
试试这样投射。 ~0 被提升为 int,它是有符号的,所以当你移位时它带有符号位
unsigned leftmost1 = ((unsigned)(~0)>>20);
printf("leftmost1 %u\n", leftmost1);
在第一种情况下,您正在进行 有符号右移 ,因为 ~0
会产生有符号值。带符号右移的确切行为是实现定义的,但大多数平台(包括您的平台)都会扩展符号位,因此对于您输入的 "all ones".
来说,移位是空操作
在第二种情况下,您正在进行无符号右移,因为 leftmost1
是一个 unsigned
值。所以你从左边移入零。
如果你想在没有中间赋值的情况下进行无符号移位,你可以这样做:
(~0u) >> 20
其中 u
后缀表示无符号文字。
0
的类型为 int
。 ~0
在典型的二进制补码机上是 -1
。右移负数具有实现定义的结果,但常见的选择是移入 1
位,这对于 -1
保持数字不变(即 -1 >> anything
是 -1
)。
您可以通过编写 0u
(unsigned int
类型的文字)来解决此问题。这会强制操作在 unsigned int
中完成,如您的第二个示例:
unsigned leftmost1 = ~0;
这一行相当于 unsigned leftmost1 = -1
,它隐式地将 -1(一个带符号的整数)转换为 UINT_MAX
。下面的操作 (leftmost1 >> 20
) 然后使用无符号算术。
~0
是一个 int
。所以你的第一段代码不等同于第二段,它等同于
int tmp = ~0;
tmp = tmp >> 20;
unsigned leftmost1 = tmp;
当您右移一个负数时,您会看到符号扩展的结果。
我以为我在 this answer 中找到了类似的东西,但在那种情况下,他们没有将表达式的结果分配给变量。在我的例子中,我正在分配它,但表达式的位移位部分没有效果。
unsigned leftmost1 = ((~0)>>20);
printf("leftmost1 %u\n", leftmost1);
Returns
leftmost1 4294967295
鉴于
unsigned leftmost1 = ~0;
leftmost1 = leftmost1 >> 20;
printf("leftmost1 %u\n", leftmost1);
给我
leftmost1 4095
我希望将逻辑分成两行不会有影响,为什么结果不同?
试试这样投射。 ~0 被提升为 int,它是有符号的,所以当你移位时它带有符号位
unsigned leftmost1 = ((unsigned)(~0)>>20);
printf("leftmost1 %u\n", leftmost1);
在第一种情况下,您正在进行 有符号右移 ,因为 ~0
会产生有符号值。带符号右移的确切行为是实现定义的,但大多数平台(包括您的平台)都会扩展符号位,因此对于您输入的 "all ones".
在第二种情况下,您正在进行无符号右移,因为 leftmost1
是一个 unsigned
值。所以你从左边移入零。
如果你想在没有中间赋值的情况下进行无符号移位,你可以这样做:
(~0u) >> 20
其中 u
后缀表示无符号文字。
0
的类型为 int
。 ~0
在典型的二进制补码机上是 -1
。右移负数具有实现定义的结果,但常见的选择是移入 1
位,这对于 -1
保持数字不变(即 -1 >> anything
是 -1
)。
您可以通过编写 0u
(unsigned int
类型的文字)来解决此问题。这会强制操作在 unsigned int
中完成,如您的第二个示例:
unsigned leftmost1 = ~0;
这一行相当于 unsigned leftmost1 = -1
,它隐式地将 -1(一个带符号的整数)转换为 UINT_MAX
。下面的操作 (leftmost1 >> 20
) 然后使用无符号算术。
~0
是一个 int
。所以你的第一段代码不等同于第二段,它等同于
int tmp = ~0;
tmp = tmp >> 20;
unsigned leftmost1 = tmp;
当您右移一个负数时,您会看到符号扩展的结果。