打印存储为字符串的十六进制值会产生意外输出

时间:2015-08-06 10:10:43

标签: c string char hex printf

我在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值?

3 个答案:

答案 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的预期类型。因此,输出是错误的,因为intunsigned int不是同一类型。 [参见§6.7.2,C11]。所以,没有像

这样的明确演员
printf("%02x\n", (unsigned int)chars[0]);

它调用undefined behaviour

FWIW,如果你有一个C99支持的编译器,你可以使用hh长度修饰符解决这个问题,比如

 printf("%02hhx\n", (unsigned char)chars[0]);

答案 2 :(得分:0)

这是因为签名延期。

这将按预期工作:

printf("%02x\n", (unsigned char)chars[0]);