为什么1字节变量的按位补码返回4字节值?

时间:2017-12-20 19:00:54

标签: c bitwise-operators

让我们举例说明以下两个1字节变量:

uint8_t x1 = 0x00;
uint8_t x2 = 0xFF;

打印按位补码时,结果为4字节变量:

printf("%02X -> %02X; %02X -> %02X\n", x1, ~x1, x2, ~x2);
00 -> FFFFFFFF; FF -> FFFFFF00

我知道这可以解决"使用铸造或掩蔽:

printf("%02X -> %02X; %02X -> %02X\n", x1, (uint8_t) ~x1, x2, (uint8_t) ~x2);
00 -> FF; FF -> 00
printf("%02X -> %02X; %02X -> %02X\n", x1, ~x1&0xFF, x2, ~x2&0xFF);
00 -> FF; FF -> 00

但为什么首先出现非直觉行为?

2 个答案:

答案 0 :(得分:2)

许多计算机处理器的大多数操作都具有“字”大小。例如,在32位机器上,可能存在加载32位的指令,存储32位的指令,将一个32位数加到另一位的指令,等等。

在这些处理器上,使用其他尺寸可能会令人讨厌。可能没有将16位数乘以另一个16位数的指令。 C在这些机器上长大。它的设计是为了int(或unsigned int)“无论大小对你正在运行的机器有什么好处”,charshort都适合存放内存,但是,一旦它们从内存加载到处理器寄存器中,C就像它们int一样使用它们。

这简化了早期C编译器的开发。编译器不必通过执行32位补码指令,然后执行AND指令来删除不需要的高位来实现补码。它只做了一个简单的32位补码。

我们今天可以用不同的方式开发语言,但C承担着这种遗产。

答案 1 :(得分:1)

当您将~运算符应用于x1x2时,这些值首先会受到整数提升,因为uint8_t小于int。然后将运算符应用于提升值。

所以~x1确实是~0x00000000(即0xFFFFFFFF)而~x2确实是~0x000000FF(即FFFFFF00)。这就是为什么你得到你正在获得的价值。

此外,%x格式说明符需要unsigned int这样打印。

您需要使用%hhx作为格式说明符。这表示unsigned char参数。

printf("%02hhX -> %02hhX; %02hhX -> %02hhX\n", x1, ~x1, x2, ~x2);