7

我试图了解按位运算符对有符号和无符号类型的行为。根据 ISO/IEC 文件,以下是我的理解。

左移运算符

  • 的结果E1 << E2是 E1 左移 E2 位位置

  • 由于左移而空出的位将用零填充。

  • E1 有符号非负: E1 << E2如果该值可以由结果类型表示,则将得出 E1 乘以 E2 的 2 次方。

  • Q1:签名底片呢?

  • Q2:我无法理解以下上下文中“减少模数”的含义。“如果 E1 具有无符号类型,则结果的值为 E1 × 2E2 ,比结果类型中可表示的最大值多模一减少”

右移运算符

  • 结果E1 >> E2是 E1 右移 E2 位位置。

  • E1 as signed non-negative/unsigned : 结果的值是 E1 / 2E2 商的整数部分

  • Q3:我看到的有符号负整数,有些书定义空位将被填充。请1详细说明在有符号负整数上使用右移运算符。

4

4 回答 4

8

Q1:左移运算符对有符号整数类型的负值的行为未定义,当结果E1 * 2^E2在类型中不可表示时,有符号整数类型的正值的行为也是如此。

这在标准(n1570 草案)的第 6.5.7 节第 4 和第 5 段中明确提到:

4 的结果E1 << E2E1左移的E2位位置;空出的位用零填充。如果E1具有无符号类型,则结果的值为 ,以E1 × 2^E2比结果类型中可表示的最大值大一为模减少。如果E1具有带符号类型和非负值,并且E1 × 2^E2可以在结果类型中表示,那么这就是结果值;否则,行为未定义。

Q2:比无符号整数类型中可表示的最大值多一模的归约意味着在左侧移出的位被简单地丢弃。

在数学上,如果无符号类型的最大值是2^n - 1(并且它始终是这种形式),则E1左移一位的结果是从 0 到差的范围内E2的值V2^n - 1

(E1 * 2^E2 - V)

能被 整除2^n,也就是说,它是除以 时得到的余E1 * 2^E22^n

Q3:右移有符号整数类型的负值的行为是实现定义的。最常见的行为(至少在二进制补码机器上)是算术移位,也就是说,结果是四舍五入的商(向负无穷大)。

5 结果E1 >> E2E1右移的E2位位置。如果E1有无符号类型或E1有符号类型和非负值,则结果的值是 的商的整数部分E1 / 2^E2如果E1具有带符号类型和负值,则结果值是实现定义的。

于 2012-11-24T19:11:08.513 回答
5
  • 回复:Q1
    如果 E1 为负数,则行为未定义。

  • 回复:Q2无符号算术是“循环的”,也就是说,它再次
    环绕。就好像每个计算都是以 UINT_MAX+1 为模完成的。另一种思考方式是简单地丢弃不适合左侧的多余位。UINT_MAX + 10

  • 回复:Q3
    如果 E1 为负,则结果是实现定义的。也就是说,它取决于您的机器/编译器/选项,但必须在某处记录(“定义”)行为,通常是编译器手册。两种流行的选择是用 1(算术移位)或 0(逻辑移位)填充左侧的输入位。

于 2012-11-24T19:10:37.000 回答
2

如果您真的想了解按位移位运算符。看看这些简单的规则:

1)左移时,E1 << E2,右边所有的空位都用零填充,不管数字是有符号还是无符号,总是会移入零。

2) 在左移时,E1 >> E2,左侧所有的空位,如果数字为正数将为 0,如果数字为负数则为 1。请记住,无符号数永远不会是负数。即使数字是负数,某些实现也可能在某些机器上用 0 填充它们,所以永远不要依赖它。

所有其他情况都可以用这两个简单的规则来解释。现在如果你想知道移位后结果的值,只需在纸上手动写数字和移位的位表示,并使用这两个规则在空白处输入位。然后您将能够更好地理解位移是如何工作的。

For example lets take int i = 7;
i<<2
now i = 0000 0000 0000 0000 0000 0000 0000 0111
perform two left shits according to rule 1 would be:

0000 0000 0000 0000 0000 0000 0001 1100

这将使其值为 28 ( E1 * 2E2 = 7 *2*2 = 28),这与位模式表示的相同。

现在让我解释一下“减少模”的事情,如果你移动一个大数字,那么左边的位会丢失,“减少模”会补偿它,所以如果你的结果值大于最大值数据类型可以保持,左边的位将丢失,然后:结果 = (E1*2*E2) % (maximumValue + 1)。

对于其他各种情况,请牢记上述规则,你很好:)

于 2012-11-24T19:28:44.767 回答
1

Q2:“value reduce modulo X”在数学中的意思是“value mod X”,在C中可以写成“value % X”。这部分只是解释了整数溢出是如何工作的。

于 2012-11-24T19:10:48.007 回答