【问题标题】:Right shift operator for signed numbers [duplicate]有符号数的右移运算符[重复]
【发布时间】:2014-04-29 15:17:19
【问题描述】:

我正在阅读 C 中的移位运算符。

右移 n 位除以 2 加到 n。移动有符号值可能会失败,因为对于负值,结果永远不会超过 -1:-5 >> 3-1 而不是 0-5/8

我的问题是为什么转换有符号值可能会失败?

为什么-5 >> 3 的值是-1 而不是零?

请解释一下。

【问题讨论】:

  • 因为右移复制了符号位。如果以负数开头,则以负数结尾(二进制中的所有1,即2的补码中的-1)。
  • @oakad 例如 -5 表示为一个字节的 1000 0101。如果我们对 ge 1111 0000 进行右移。我们如何得到 -1?
  • @venkysmarty -5 in 8 bits 是 11111011。右移 3 会得到 11111111。en.wikipedia.org/wiki/Two%27s_complement
  • 一些不请自来的建议:仅在您真正关心位模式时才使用位移位。当您关心变量的值作为实际整数时,请使用算术运算。此外,当您使用位移位时,只能在无符号类型上使用。如果你位移一个负整数,它的实现取决于会发生什么。
  • @oakad:有符号量的右移行为不能保证是算术移位(移入与最高有效位相同的位)或逻辑移位(移入零);根据标准,两者都是允许的。

标签: c++ c


【解决方案1】:

它只是实现定义的:

从 5.8 移位运算符开始

操作数应为整数或非范围枚举类型,并且 进行积分促销。结果的类型是 提升的左操作数。如果正确,则行为未定义 操作数为负数,或大于或等于 提升的左操作数

[...]

如果 E1 具有带符号类型和负值,则结果值是实现定义的。

【讨论】:

  • 你好像左右混淆了。相关引用是“如果 E1 具有带符号类型和负值,则结果值是实现定义的”(不是未定义的)。
【解决方案2】:

带符号整数的移位是实现定义的,但如果您使用的架构具有算术移位,您可以通过使用它非常可靠地猜测它。

这是因为负数在计算机中的存储方式。它被称为二进制补码。要切换二进制补码的符号,您需要 NOT 它的位并加 1。例如,对于 8 位整数 00011010 (26),首先您 NOT 得到 11100101,然后加 1 和获取11100110 (-26)。问题来自被设置的最重要的位。如果当您将其移入左侧时,该数字将变为正数,但如果将其放入 1,则可能的最低结果为11111111,即-1。这就是算术移位的工作原理,当您移位计算机时,会添加与最左边相同的位。

所以明确地说,这就是正在发生的事情(使用 8 位整数,因为在这种情况下它更容易并且大小是任意的):11111011 向右移动 3(所以011 消失了)并且因为最高有效位设置 3 个1s 插入顶部,因此您得到11111111,即-1。

【讨论】:

  • 这种情况是实现定义的,不是未定义的。
  • 已修复。谢谢指正。
猜你喜欢
  • 2013-01-08
  • 1970-01-01
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2013-10-03
相关资源
最近更新 更多