说我要打印unsigned char
:
unsigned char x = 12;
这是正确的。这样:
printf("%d",x);
或者这个:
printf("%u",x);
事情就在其他地方我遇到过这样的讨论:
- 即使ch更改为unsigned char,代码的行为也不是由C标准定义的。这是因为unsigned char被提升为int(在普通的C实现中),因此将int传递给printf以获取指定符%u。但是,%u需要unsigned int,因此类型不匹配,C标准不定义行为
- 您的评论不正确。 C11标准规定转换说明符必须与函数参数本身的类型相同,而不是提升类型。这一点在hh长度修饰符的描述中也有具体说明:"参数将根据整数提升进行提升,但在打印之前,其值应转换为有符号字符或无符号字符。34;
哪个是正确的?任何可靠的消息来源都说这个问题? (从这个意义上讲,我们还应该用%d打印unsigned short
int,因为它可以提升为int
?)。
答案 0 :(得分:8)
正确的是*:
printf("%d",x);
这是因为默认参数促销,因为printf()
是可变参数函数。这意味着unsigned char
值始终会提升为int
。
从N1570(C11草案)6.5.2.2/6
函数调用(强调我的未来):
如果表示被调用函数的表达式具有类型 不包含原型,执行整数促销 每个参数和类型
float
的参数都被提升为double
。这些被称为默认参数促销。
和6.5.2.2/7
子条款告诉:
函数原型声明符中的省略号表示法导致 参数类型转换在最后声明的参数后停止。 默认参数促销在尾随参数上执行。
这些整数促销在6.3.1.1/2
布尔,字符和整数中定义:
如果
int
可以代表原始类型的所有值(受限制 通过宽度,对于位字段),该值被转换为int
; 否则,它将转换为unsigned int
。这些被称为 整数提升 .58)所有其他类型均未被整数更改 促销。
此引文回答了您unsigned short
的第二个问题(请参阅下面的评论)。
*超过8位unsigned char
除外(例如它可能占用16位),请参阅@ chux的answer。
答案 1 :(得分:7)
unsigned char x = 12
的正确格式说明符取决于许多事项:
如果INT_MAX >= UCHAR_MAX
(通常是这种情况),请使用"%d"
。在这种情况下,unsigned char
会提升为int
。
printf("%d",x);
否则请使用"%u"
(或"%x"
,"%o"
)。在这种情况下,unsigned char
会提升为unsigned
。
printf("%u",x);
最新的编译器支持"hh"
长度修饰符,可以补偿这种歧义。由于可变参数的标准促销,x
应int
升级为unsigned
或printf()
,unsigned char
会在打印前将其转换为printf("%hhu",x);
。
"hh"
如果处理没有printf("%u", (unsigned) x);
的旧编译器或寻求高度可移植的代码,请使用显式转换
unsigned short
相同的问题/答案适用于INT_MAX >= USHRT_MAX
,期待"h"
并使用"hh"
代替{{1}}。
答案 2 :(得分:2)
unsigned char
和unsigned short
都可以随时使用%u
安全打印。默认参数提升会将其转换为int
或unsigned int
。如果它们被提升为后者,一切都很好(格式说明符和传递的类型匹配),否则C11(n1570)6.5.2.2 p6,第一个子弹,适用:
- 一个提升类型是有符号整数类型,另一个提升类型是相应的无符号整数类型,并且该值可在两种类型中表示;
标准非常明确,默认参数促销适用于printf
的可变参数,例如对于(大多数无用的)h
和hh
长度修饰符(同上.7.21.6.1 p7,emph.mine)再次提及:
hh
- 指定以下d
,i
,o
,u
,x
或X
转换说明符适用于signed char
或unsigned char
参数(参数将根据整数提升进行提升,但其值应转换为signed char
或打印前unsigned char
); [...]
答案 3 :(得分:1)
对于跨平台开发,我通常使用inttypes.h
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/inttypes.h.html
此标头(符合C99标准)定义了基本类型的所有printf类型。所以如果你想要一个uint8_t(我强烈建议使用的语法而不是unsigned char)我会使用
#include <inttypes.h>
#include <stdint.h>
uint8_t x;
printf("%" PRIu8 "\n",x);