在C中打印十六进制字符

时间:2011-11-09 03:59:17

标签: c hex printf

我正在尝试读取一行字符,然后打印出十六进制字符的等效字符。

例如,如果我的字符串为"0xc0 0xc0 abc123",其中前两个字符为十六进制c0,其余字符为ASCII abc123,那么我应该< / p>

c0 c0 61 62 63 31 32 33

然而,使用printf的{​​{1}}给了我

%x

如何在没有ffffffc0 ffffffc0 61 62 63 31 32 33 的情况下获得我想要的输出?为什么只有c0(和80)有"ffffff",而不是其他字符?

7 个答案:

答案 0 :(得分:109)

您看到了ffffff,因为char已在您的系统上签名。在C中,诸如printf之类的vararg函数会将小于int的所有整数提升为int。由于char是一个整数(在您的情况下为8位有符号整数),因此您的字符将通过符号扩展名提升为int

由于c080具有前导1位(并且作为8位整数为负),因此它们将被符号扩展,而样本中的其他符号则不会。< / p>

char    int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061

这是一个解决方案:

char ch = 0xC0;
printf("%x", ch & 0xff);

这将屏蔽高位并仅保留您想要的低8位。

答案 1 :(得分:54)

确实,有类型转换为int。 您也可以使用%hhx说明符强制类型为char。

printf("%hhX", a);

在大多数情况下,您还需要设置最小长度以用零填充第二个字符:

printf("%02hhX", a);

ISO / IEC 9899:201x说:

  

7长度修饰符及其含义为:   hh指定以下d,i,o,u,x或X转换说明符适用于a   signed char或unsigned char参数(参数将具有   按整数促销推广,但其价值应为   在打印之前转换为signed char或unsigned char);或者那个   以下

答案 2 :(得分:26)

您可以创建一个unsigned char:

unsigned char c = 0xc5;

打印它将提供C5而不是ffffffc5

只有大于127的字符用ffffff打印,因为它们是否定的(字符已签名)。

或者您可以在打印时投射char

char c = 0xc5; 
printf("%x", (unsigned char)c);

答案 3 :(得分:11)

您可能将值0xc0存储在char变量中,可能是签名类型,并且您的值为负(最高位设置)。然后,在打印时,它被转换为int,并且为了保持语义等价,编译器用0xff填充额外的字节,因此负int将具有与您的负char相同的数值。 1}}。要解决此问题,请在打印时转换为unsigned char

printf("%x", (unsigned char)variable);

答案 4 :(得分:11)

您可以使用hh告诉printf该参数是无符号字符。使用0获取零填充,使用2将宽度设置为2. xX,用于低/大写十六进制字符。

uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"

编辑:如果读者担心2501的断言,这是不正确的&#39;正确的&#39;格式说明符我建议他们再次阅读printf link。具体做法是:

  

即使%c需要int参数,由于调用可变参数函数时发生的整数提升,传递char也是安全的。

     

固定宽度字符类型(int8_t等)的正确转换规范在标题<cinttypes>(C ++)或<inttypes.h>(C)中定义(尽管PRIdMAX,PRIuMAX, etc与%jd,%ju等同义)

至于他关于signed vs unsigned的观点,在这种情况下它并不重要,因为值必须始终为正且容易适合有符号的int。无论如何,没有签名的hexyximal格式说明符。

编辑2 :(&#34;何时承认 - 重新错误&#34;版本):

如果您阅读了第311页的the actual C11 standard(PDF格式的329),您会发现:

  

hh:指定以下diouxX转换说明符适用于signed charunsigned char参数(参数将根据整数提升进行提升,但在打印前其值应转换为signed charunsigned char);或者以下n转换说明符适用于指向signed char参数的指针。

答案 5 :(得分:2)

您可能正在从已签名的char数组中打印。从unsigned char数组打印或用0xff掩盖值:例如ar [i]&amp; 0xFF的。由于高(符号)位已设置,因此c0值正在进行符号扩展。

答案 6 :(得分:-1)

尝试这样的事情:

int main()
{
    printf("%x %x %x %x %x %x %x %x\n",
        0xC0, 0xC0, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33);
}

产生这个:

$ ./foo 
c0 c0 61 62 63 31 32 33