Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用C语言打印十六进制字符_C_Hex_Printf - Fatal编程技术网

用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
将宽度设置为2
x
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