【问题标题】:C print hex bytesC 打印十六进制字节
【发布时间】:2017-09-10 20:16:48
【问题描述】:

我在 C 程序中有我想要迭代的十六进制数据的代码,例如打印出每个十六进制字节:

char input[] = "\x31\xd2\xb2\x30";
for (int i = 0; i < strlen(input); i++) {
    printf("%02X\n", input[i]);
}

但是,输出不是我所期望的,例如上面的打印:

31
FFFFFFD2
FFFFFFB2
30

我还尝试将输出转换为 (unsigned int),但我收到了相同的输出。

有人能指出这个简单脚本的问题吗?

【问题讨论】:

  • 在您的系统上,char 可能是signed。所以数据\xd2 是负数。您将该值传递给printf,它会被提升为int,它也已签名。但是格式说明符 %X 需要 unsigned int 并相应地解释二进制数据。这是未定义的行为。

标签: c printing printf


【解决方案1】:

传递给 printf 的参数是符号扩展的,除非您将它们转换为像这样的无符号类型:

printf("%02X\n", (unsigned char)input[i]);

【讨论】:

  • 哎呀,你是对的。我使用了一个无符号整数,但它当然是一个字符。
【解决方案2】:

printf("%02X") 需要一个无符号整数;传递char 类型的负值(char 类型的0xD2 是负值)将导致将负char 值提升为32 位无符号整数,从而用1 填充前导位和最后产生0xFFFFFFD2。然后打印出来。

要克服这个问题,您可以“告诉”printf 将提供的值作为 8 位值:

printf("%02hhX\n", input[i]) 

另一种选择是将input 声明为unsigned char,因为这样0xD2 不会被视为“负数”,而升级到32 位将按预期工作:

unsigned char input[] = "\x31\xd2\xb2\x30";

请注意,strlen 将需要转换输入,即strlen((char*)intput)。

【讨论】:

    【解决方案3】:

    char input[] 必须是 unsigned char input[]。这就是您存储二进制字节的方式。

    【讨论】:

      【解决方案4】:
      // You can use like this  
      
      char input[] = "\x31\xd2\xb2\x30";
      
      for (int i = 0; i < strlen(input); i++) {  
          printf("%02X\n", input[i] & 0xff);  
      }  
      
      Output: 
      31  
      D2  
      B2  
      30  
      

      它会屏蔽掉高位,只保留低8位。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-18
        • 2015-02-14
        • 2012-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-25
        相关资源
        最近更新 更多