我在C语言中使用字符串定义的十六进制数字:
char chars[] = "\xfb\x54\x9c\xb2\x10\xef\x89\x51\x2f\x0b\xea\xbb\x1d\xaf\xad\xf8";
然后我想将这些值与另一个值进行比较。它不起作用,如果我打印的值如下:
printf("%02x\n", chars[0]);
它写fffffffb
。为什么这样以及如何准确地获得fb
值?
答案 0 :(得分:6)
这是因为符号扩展。
更改
printf("%02x\n", chars[0]);
到
printf("%02x\n", (unsigned char)chars[0]);
%x
格式说明符将在32位机器上读取4 bytes
。由于您已将chars
声明为字符数组,因此在获取值fb
(负值)时,符号将扩展为fffffffb
,其中fb
的MSB设置为它之前的所有其他位。
有关详细信息sign extension
,请参阅此处如果您已将char chars[]
声明为unsigned char chars[]
,则打印件将按预期进行。
答案 1 :(得分:2)
根据%x
格式说明符与fprintf()
o,u,x,X
unsigned int参数转换为unsigned八进制( o ),unsigned 样式 dddd 中的十进制( u )或无符号十六进制表示法(x或X); [...]
因此,%x
的预期参数类型为unsigned int
。
现在,printf()
是一个可变参数函数,只有默认促销规则应用于其参数。在您的代码中,chars
是一个类型char
的数组(其签名是依赖于实现的),如果是
printf("%02x\n", chars[0]);
chars[0]
的值被提升为int
,这不是%x
的预期类型。因此,输出是错误的,因为int
和unsigned int
不是同一类型。 [参见§6.7.2,C11
]。所以,没有像
printf("%02x\n", (unsigned int)chars[0]);
FWIW,如果你有一个C99支持的编译器,你可以使用hh
长度修饰符解决这个问题,比如
printf("%02hhx\n", (unsigned char)chars[0]);
答案 2 :(得分:0)
这是因为签名延期。
这将按预期工作:
printf("%02x\n", (unsigned char)chars[0]);