【问题标题】:Printing the hex value stored as a string gives unexpected output打印存储为字符串的十六进制值会产生意外的输出
【发布时间】:2015-10-29 10:28:14
【问题描述】:

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

【问题讨论】:

  • 处理二进制数据时,您总是希望使用unsigned char。我会更改声明而不是添加演员表。

标签: c string char hex printf


【解决方案1】:

这是因为符号扩展。

改变

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[],则打印结果将符合预期。

【讨论】:

    【解决方案2】:

    根据标准提及 %x 格式说明符和 fprintf()

    o,u,x,X

    无符号整数参数转换为无符号八进制(o),无符号 dddd 风格的十进制 (u) 或 无符号十六进制表示法(x 或 X); [...]

    因此,%x 的预期参数类型是 unsigned int

    现在,printf() 是一个可变参数函数,只有默认提升规则应用于其参数。在您的代码中,charschar 类型的数组(其符号取决于实现),以防

    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]);
    

    【讨论】:

    • [次要旁注]:我认为,C 开发人员之间有一个共同的共识,即 %x 格式说明符对 int 对象有效,它持有 nonnegative价值。例如{ int i = 100; printf("%x\n", i); } 是可以接受的,即使类型不是unsigned int。但是,严格来说是UB,对吧?
    • @GrzegorzSzpetkowski 是的,这就是我所知道的。 :-)
    【解决方案3】:

    这是因为符号扩展。

    这将按您的预期工作:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2013-11-11
      • 2012-12-01
      • 2021-12-07
      • 1970-01-01
      • 2014-10-07
      相关资源
      最近更新 更多