用C语言打印十六进制字符
我试着读入一行字符,然后打印出这些字符的十六进制等价物用C语言打印十六进制字符,c,hex,printf,C,Hex,Printf,我试着读入一行字符,然后打印出这些字符的十六进制等价物 uint8_t a = 0x0a; printf("%02hhX", a); // Prints "0A" printf("0x%02hhx", a); // Prints "0x0a" 例如,如果我有一个字符串“0xc0 0xc0 abc123”,其中前两个字符是十六进制的c0,其余字符是ASCII的abc123,那么我应该得到 c0 c0 61 62 63
uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"
例如,如果我有一个字符串“0xc0 0xc0 abc123”
,其中前两个字符是十六进制的c0
,其余字符是ASCII的abc123
,那么我应该得到
c0 c0 61 62 63 31 32 33
但是,printf
使用%x
会给我
ffffffc0 ffffffc0 61 62 63 31 32 33
如果没有
“ffffff”
,如何获得所需的输出?为什么只有c0(和80)有ffffff
,而没有其他字符?您看到的是ffffff
,因为char
是在您的系统上签名的。在C语言中,诸如printf
之类的vararg函数将所有小于int
的整数提升为int
。由于char
是一个整数(在您的例子中是8位有符号整数),您的字符将通过符号扩展升级为int
由于c0
和80
具有前导1位(作为8位整数为负数),因此它们正在进行符号扩展,而示例中的其他部分则没有
char int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061
这里有一个解决方案:
char ch = 0xC0;
printf("%x", ch & 0xff);
这将屏蔽高位,只保留所需的低位8位。您可能是从有符号字符数组打印的。从无符号字符数组打印或使用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
您可能正在将值0xc0存储在
char
变量中,该变量可能是有符号类型,并且您的值为负值(最高有效位集)。然后,在打印时,它被转换为int
,为了保持语义等价,编译器用0xff填充额外的字节,因此负数int
将具有与负数char
相同的数值。要解决此问题,只需在打印时转换为无符号字符
:
printf("%x", (unsigned char)variable);
char c = 0xc5;
printf("%x", (unsigned char)c);
实际上,存在到int的类型转换。 您还可以使用%hhx说明符将类型强制为char
printf("%hhX", a);
在大多数情况下,您还需要设置最小长度,以便用零填充第二个字符:
printf("%02hhX", a);
ISO/IEC 9899:201x规定:
7长度修饰符及其含义为:
hh指定以下d、i、o、u、x或x转换说明符应用于
有符号字符或无符号字符参数(该参数将具有
已根据整数升迁进行升迁,但其值应为
打印前转换为有符号字符或无符号字符);或者
追随者
您可以创建无符号字符:
unsigned char c = 0xc5;
打印它将给出C5
,而不是FFFFFF C5
只有大于127的字符才使用ffffff
打印,因为它们是负数(字符是有符号的)
或者,您可以在打印时强制转换字符
:
printf("%x", (unsigned char)variable);
char c = 0xc5;
printf("%x", (unsigned char)c);
您可以使用
hh
来判断参数是无符号字符。使用0
获得零填充,使用2
将宽度设置为2x
或x
用于小写/大写十六进制字符
uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"
编辑:如果读者担心2501的断言,即这不是“正确”的格式说明符,我建议他们再次阅读。具体而言: 尽管%c需要int参数,但传递字符是安全的,因为在调用变量函数时会发生整数提升 固定宽度字符类型(int8_t等)的正确转换规范在标题
(C++)或
(C)中定义(尽管PRIdMAX、PRIuMAX等与%jd、%ju等同义)
至于他关于有符号与无符号的观点,在这种情况下,这并不重要,因为值必须始终是正的,并且很容易适应有符号整数。无论如何,没有带符号的十六进制格式说明符
编辑2:(“何时承认错误”编辑):
如果您阅读第311页(PDF的329页),您会发现:
hh:指定下列d
、i
、o
、u
、x
或x
转换说明符应用于有符号字符
或无符号字符
参数(参数将根据整数升迁进行升迁,但其值应在打印前转换为有符号字符
或无符号字符
);或者以下n
转换说明符应用于指向有符号字符
参数的指针
我的解决方案是使用转换为
无符号字符
,在gcc4.6 for x86-64中使用一条较小的指令…也许我能帮上忙。这是(技术上)未定义的行为,因为说明符x
需要无符号类型,但ch提升为int。正确的代码只需将ch强制转换为无符号,或使用强制转换为无符号字符,说明符:hhx
。如果我有printf(“%x”,0)
,不打印任何内容。它不打印任何内容,因为最小值设置为0。若要解决此问题,请尝试printf(“%.2x”,0);
这将使绘制的最小字符数增加到2。若要设置最大值,请在为什么printf(“%x”,ch&0xff)
应该比只使用printf(“%02hhhx”,a)
更好,就像@barrout_lobster's?+1一样,这是真正的最佳答案,显式键入尽可能接近数据声明(但不是更接近).说明符对于类型uint8_t不正确。固定宽度类型使用特殊的打印说明符。请参阅:inttypes.h
Yeah,但所有varargs整数都隐式提升为int。这可能是,但就定义的C而言,如果不使用正确的说明符,行为是未定义的。但是%x是正确的说明符。(char
和unsigned char
被提升为i