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
答案 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以十六进制打印输出显示。