在C中打印hex字符
我试图读取一行字符,然后打印出相当于字符的hex。
例如,如果我有一个string是"0xc0 0xc0 abc123" ,其中前两个字符是hex的c0 ,其余的字符是abc123的ASCII,那么我应该得到 
 c0 c0 61 62 63 31 32 33 
 但是,使用%x printf给了我 
 ffffffc0 ffffffc0 61 62 63 31 32 33 
 如何在没有"ffffff"情况下获得我想要的输出? 为什么只有c0(和80)有ffffff ,而不是其他的字符? 
 你正在看到ffffff因为char在你的系统上被签名。 在C中,可变参数如printf会将所有小于int整数提升为int 。 由于char是一个整数(在你的情况8位有符号整数),你的字符正在通过符号扩展升级到int 。 
 由于c0和80有一个前导1位(并且是8位整数的负数),所以它们正在被符号扩展,而其他样例中的其他则不是。 
 char int c0 -> ffffffc0 80 -> ffffff80 61 -> 00000061 
这是一个解决scheme:
 char ch = 0xC0; printf("%x", ch & 0xff); 
这将掩盖高位,只保留你想要的低8位。
的确,有types转换为int。 你也可以使用%hhx说明符强制types为char。
 printf("%hhX", a); 
你可以创build一个无符号的char:
 unsigned char c = 0xc5; 
 打印它会给C5而不是ffffffc5 。 
 只有大于127的字符才会用ffffff打印,因为它们是负数(char有符号)。 
 或者您可以在打印时投下char : 
 char c = 0xc5; printf("%x", (unsigned char)c); 
 您可能将值0xc0存储在charvariables中,可能是签名types,而您的值是负值(设置最重要的位)。 然后,打印时,它被转换为int ,并保持语义等价,编译器用0xff填充额外的字节,所以负的int将具有相同的负数char数值。 要解决这个问题,打印时只需转换为unsigned char : 
 printf("%x", (unsigned char)variable); 
 你可以使用hh来告诉printf参数是一个无符号的字符。 使用0获得零填充,使用2将宽度设置为2. x或X表示小写/大写hex字符。 
 uint8_t a = 0x0a; printf("%02hhX", a); // Prints "0A" printf("0x%02hhx", a); // Prints "0x0a" 
  编辑 :如果读者关心2501的断言,这是不正确的格式说明符,我build议他们再次阅读printf链接 。 特别: 
尽pipe%c需要int参数,但因为在调用可变参数函数时发生整数提升,所以传递char是安全的。
在头文件
<cinttypes>(C ++)或<inttypes.h>(C)中定义了固定宽度字符types(int8_t等)的正确转换规范(虽然PRIdMAX,PRIuMAX等与%jd,% ju等) 。
至于他关于有符号还是无符号的观点,在这种情况下,这并不重要,因为这些值必须始终是正数,并且容易符合一个有符号整数。 无论如何,没有签名的hex格式说明符。
编辑2 :(“何时承认你是错误的”版本):
如果您阅读311页上的实际C11标准 (PDF格式的329),则会发现:
hh:指定后面的
d,i,o,u,x或X转换说明符适用于带signed char或unsigned char参数(参数将根据整数提升进行提升,但其值将转换为带signed char打印之前的signed char或unsigned char); 或者下面的n转换说明符适用于指向signed char参数的指针。
您可能正在从一个签名的字符数组打印。 要么从unsigned char数组打印,要么用0xff掩码值:例如ar [i]&0xFF。 由于高(符号)位被设置,c0值被扩展符号。
尝试这样的事情:
 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