如何解释这一点,当我们将signed char转换为int / hex时会发生什么?

时间:2011-06-15 14:47:37

标签: c

signed char num = 220; //DC in hex
printf("%02X\n", num);
printf("%d\n", num);

我知道signed char只能代表-128~127,但为什么上述输出:

FFFFFFDC
-36

是什么原因?

更新

我的上述代码只针对我的问题,即what happens when we cast signed char to int/hex

4 个答案:

答案 0 :(得分:2)

正如您所指出的那样,签名汽车的最大值可以是127.然而,那里负数的原因是由于char存储在内存中的方式。所有有符号整数类型都保存符号的最后一位,0/1表示正/负。但是,编译器不检查溢出,因此当您尝试将num分配给220时,它会将值溢出到符号位,因为它无法将其放入char的前7位(字符为1个字节)。因此,当您尝试读取内存中的内容时,它会看到符号位被抛出,使编译器认为不是按预期看到大的正数,而是看到一个小的负值。因此,你看到的输出。

修改 回应您更新的问题。所有发生的事情是编译器将复制或扩展char以具有4个字节的内存,解释char的值,并在新int的内存中重写它。在你的情况下,运行时程序会认为char的值为-36而不是220,因为它在转换之前将这些位解释为带符号的char。然后,当它转换时,它只是创建一个值为-36的int。

答案 1 :(得分:1)

作为我们的起点,220 = DC为十六进制,11011100为二进制。

第一位是符号位,留下1011100. Per two's complement,如果我们补充它(得到0100011),然后加一,我们得到0100100 - 这是36。

当它将signed char转换为signed int时,它没有说“如果它是无符号的那将是220”,它说“这是-36,使它成为-36的int”,其中32-位二的补码表示是FFFFFFDC,因为它必须是int的完整大小的负值(这称为sign-extension):

+36 as a 32-bit value: 00000000000000000000000000100100
complement:            11111111111111111111111111011011
add one:               11111111111111111111111111011100

或者,以十六进制,FFFFFFDC

这就是为什么你必须小心printf("%x", ch);(和亲戚) - 如果你想获得一个两位数的值,并且字符已经签名,你可能会用八位数代替。如果您需要无符号字符,请始终指定“unsigned char”。

答案 2 :(得分:0)

您对作业的溢出,并在将其提升为int时以符号扩展名以十六进制的形式查看...请参阅What's happening in the background of a unsigned char to integer type cast?

答案 3 :(得分:0)

任何小于“int”的类型在通过“...”传递时转换为“int”。这意味着你的负char被转换为负int,其中FFF以十六进制打印输出显示。