编译器如何将打印 unsigned int 视为有符号 int?

How does the compiler treats printing unsigned int as signed int?

我想弄清楚为什么会出现以下代码:

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

a一开始会是00001010,NOT运算后会变成

进入11110101.

当一个人试图将 a 打印为有符号整数时究竟发生了什么,这使得

打印出来的结果是-11

我想我最终可能会看到 -5(根据二进制表示),但不会看到 -11

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

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。

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

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

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

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

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