【问题标题】:storing negative numbers存储负数
【发布时间】:2011-07-25 12:23:08
【问题描述】:

在下面这段代码中

int main()
{
int  a = -1;
printf("%d",a>>1);
return 0;
}

为什么它给出输出 -1。

【问题讨论】:

标签: c


【解决方案1】:

位移位仅在无符号类型上定义,对于有符号类型,它是实现定义的。 这是 R.. 的有用改进。

严格来说,它被定义为 有符号类型,只要值是 阳性,结果不 溢出,右移是 实现定义为负 价值观。另一方面,左移, 对于负值是未定义的

┌───┬──────────────┬──────────────────────────────────┬────────────────────────┐
│   │ Unsigned     │ Signed, positive                 │ Signed, negative       │
├───┼──────────────┼──────────────────────────────────┼────────────────────────┤
│<< │ well-defined │ well-defined, except on overflow │ undefined behaviour    │
│>> │ well-defined │ well-defined                     │ implementation-defined │
└───┴──────────────┴──────────────────────────────────┴────────────────────────┘

【讨论】:

  • 严格来说,它是为有符号类型定义的,只要值为正且结果不溢出,右移是为负值实现定义的。另一方面,对于负值,左移未定义
  • 根据Wikipedia: Arithmetic shift,我相信这将是C99中的“实现定义”
【解决方案2】:

因为 -1 在二进制中是 1111111...111。 a&gt;&gt;1 操作将“符号扩展”符号位,因此您再次获得 1111111...111。

【讨论】:

  • 这只是补充代码,不一定是数字的表示方式。但是,在许多平台上你是对的
  • @Arment - 同意,这绝对取决于机器。我应该指出这一点。不过,很明显,符号扩展是在这种特殊情况下发生的事情。
  • @Armen - 不知道您是否收到过之前的评论。 (对不起,你的名字打错了。)
【解决方案3】:

大多数编译器选择将有符号数上的&gt;&gt; 解释为算术移位。因此,由于该数字最初为负数(即 MSB 位为 1),在右移后,该位被另一个 1 替换以保留符号,因此您开始时会得到 -1。

【讨论】:

    【解决方案4】:

    有符号值上的&gt;&gt; 运算符可以执行算术或逻辑移位,具体取决于编译器。算术移位保留符号位,因此-1(在 2-s 补码机器上,这几天几乎是您会遇到的唯一变化)在右移时将保持 -1。 (请注意,C 标准没有明确指定有符号数上的 &gt;&gt; 是算术移位还是逻辑移位。不过,它始终是无符号数上的逻辑移位。)

    【讨论】:

      【解决方案5】:

      有符号值移位的定义取决于实现。检查编译器的文档以了解其处理方式。

      【讨论】:

        【解决方案6】:

        在内存中,如果有符号整数,则存储为 2 的补码,当从内存 {%d} 读取数据时,它会转换为原始形式,所以这里 -1 的 2 的补码将存储在内存中,假设整数占用 2 个字节,所以 @ 987654321@

        在执行a&gt;&gt;1 之后,它现在会改变0111 1111 1111 1111 我们知道,当从内存中读取数据时,它会再次转换为0 补码,所以取0111 1111 1111 1111 的2 的补码,它就像1000 0000 0000 0001 等于-1

        注意: +ve 数的 2 补码与原始二进制表示相同 2 的补码仅适用于 -ve 数。在 C 中,数字始终存储为 2 的补码形式

        【讨论】:

        • 首先,无符号数不存储为 2 的补码。对于有符号数,并非所有架构/编译器实现也都使用 2 的补码。 C 标准允许任何其他数字编码,尽管现在几乎不可能找到 1 的补码或符号幅度实现
        • @LưuVĩnhPhúc:为什么如果 unsigned 不存储为 2 的补码,则输出为 -1 #include void main() { unsigned int a = -1; printf("%d", a); }
        • 无符号数字由%u 打印,你得到了一个未定义的行为
        • 尝试在使用 1 的补码或符号大小的计算机上打印 -1 并查看
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-13
        • 1970-01-01
        • 2012-04-26
        • 2012-01-28
        • 1970-01-01
        • 2022-12-15
        • 2021-06-13
        相关资源
        最近更新 更多