Answers:
您会看到ffffff
因为char
已在系统上签名。在C语言中,可变参数的功能,比如printf
将促进所有整数小于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位。
unsigned char
强制转换为x86-64的gcc4.6中的指令更小...
x
需要一个无符号类型,但是ch被提升为int类型。正确的代码只需将ch强制转换为无符号,或者使用强制转换为unsigned char和说明符:hhx
。
printf("%x", 0)
,则什么也不会打印。
printf("%.2x", 0);
将将绘制的最小字符提升为2。要设置最大值,请在前面加上。与数字。例如,您只能强制执行以下操作绘制2个字符printf("%2.2x", 0);
您可以hh
用来告诉printf
该参数是一个无符号字符。使用0
以获得零填充和2
所述宽度设置为2 x
或X
更低/大写十六进制字符。
uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"
编辑:如果读者担心2501的断言是某种程度上不是“正确”格式说明符,我建议他们再次阅读该printf
链接。特别:
即使%c期望使用int参数,也可以安全地传递char,因为调用可变参数函数时会发生整数提升。
在标头
<cinttypes>
(C ++)或<inttypes.h>
(C )中定义了固定宽度字符类型(int8_t等)的正确转换规范(尽管PRIdMAX,PRIuMAX等与%jd,%ju等同义)。
至于他关于有符号与无符号的观点,在这种情况下没有关系,因为这些值必须始终为正,并且可以轻松地放入带符号的int中。无论如何,没有带符号的十六进制格式说明符。
编辑2:(“当您承认错误时”版):
如果您阅读第311页的实际C11标准(PDF的329),则会发现:
HH:用于指定后续的
d
,i
,o
,u
,x
,或X
转换说明适用于一个signed char
或unsigned char
参数(该参数将已经根据整数促销促进,但它的值应被转换成signed char
或unsigned char
打印之前); 或以下n
转换说明符适用于指向signed char
参数的指针。
inttypes.h
char
并unsigned char
提升为int
)[ en.cppreference.com/w/cpp/language/variadic_arguments]。您只需要对平台中不适合的内容使用PRI规范int
-例如unsigned int
。
%x
对于unsigned int不是int是正确的。char和unsigned char类型被提升为int类型。另外,不能保证将uint8_t定义为无符号字符。
"\xc0\xc0abc123"