我最近遇到this question,其中OP在打印变量的十六进制值时遇到问题。我相信问题可以归结为following code:
#include <stdio.h>
int main() {
char signedChar = 0xf0;
printf("Signed\n”);
printf(“Raw: %02X\n”, signedChar);
printf(“Masked: %02X\n”, signedChar &0xff);
printf(“Cast: %02X\n", (unsigned char)signedChar);
return 0;
}
这给出了以下输出:
Signed
Raw: FFFFFFF0
Masked: F0
Cast: F0
用于每个打印的格式字符串是%02X
,我总是将其解释为“将提供的int
打印为至少有两位数的十六进制值”。
第一种情况将signedCharacter作为参数传递并输出错误的值(因为int
的其他三个字节都设置了所有位。)
第二种情况通过对值应用位掩码(0xFF
)来解决此问题,以删除存储char
的除最低有效字节之外的所有字节。这有用吗?当然:signedChar == signedChar & 0xFF
?
第三种情况是通过将字符转换为unsigned char
来解决问题(这似乎清除了前三个字节?)。
对于上述三种情况中的每一种情况,有人可以告诉我是否定义了行为?如何/在哪里?
答案 0 :(得分:10)
我不认为这种行为完全由c标准定义。毕竟它取决于有符号值的二进制表示。我将描述它是如何工作的。
printf(“Raw: %02X\n”, signedChar);
可以写为(char)0xf0
的 (char)-16
转换为(int)-16
,其十六进制表示为0xfffffff0
。
printf(“Masked: %02X\n”, signedChar &0xff);
0xff
属于int
类型,因此在计算&
之前,signedChar
会转换为(int)-16
。
((int)-16) & ((int)0xff)
== (int)0x000000f0
。
printf(“Cast: %02X\n", (unsigned char)signedChar);
可以写为(unsigned char)0xf0
的 (unsigned char)240
转换为(unsigned int)240
为十六进制0x000000f0