【问题标题】:How does the compiler treats printing unsigned int as signed int?编译器如何将打印 unsigned int 视为已签名 int?
【发布时间】:2015-08-02 18:08:05
【问题描述】:

我正在尝试找出以下代码的原因:

{
  unsigned int a = 10;
  a = ~a;
  printf("%d\n", a);
}

a 开头为00001010,NOT 操作后,将转换

转入11110101

当尝试将a 打印为有符号整数时会发生什么,这使得

打印结果为-11

我以为我最终会看到-5(根据二进制表示),但不是-11

我很高兴得到关于此事的澄清。

【问题讨论】:

    标签: c printing unsigned-integer


    【解决方案1】:

    2 的补码表示法用于存储负数。

    数字 10 在 4 字节二进制中是 0000 0000 0000 0000 0000 0000 0000 1010。

    a=~a 使 a 的内容为 1111 1111 1111 1111 1111 1111 1111 0101。

    当被视为有符号整数时,这个数字将告诉编译器 取最高位为符号,其余为幅度。

    msb 中的 1 使数字成为负数。

    因此对剩余位执行 2 的补码运算。

    因此 111 1111 1111 1111 1111 1111 1111 0101 变为 000 0000 0000 0000 0000 0000 0000 1011。

    这在解释为十进制整数时变为 -11。

    【讨论】:

    • 迂腐评论:C 不需要 2s 补码。它甚至没有指定如何存储数字。 x86 和 ARM,使用 2s 补码
    【解决方案2】:

    当你写 a = ~a; 时,你将 a 中的每一位反转,也称为 1 的补码。

    负数的表示被声明为依赖于实现,这意味着不同的架构可能对-10-11 有不同的表示。

    假设普通处理器上的 32 架构使用 2 的补码表示负数 -1 将表示为 FFFFFFFF(十六进制)或 32 位到 1。

    ~a 将表示为 = FFFFFFF5 或二进制 1...10101,即 -11 的表示。

    注意:第一部分始终相同且不依赖于实现,~a FFFFFFF5 在任何 32 位架构上。只有第二部分(-11 == FFFFFFF5)依赖于实现。顺便说一句,在使用 1 的补码表示负数的架构上,它会是 -10。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多