[英]Why does printf pad an 8-bit char to 32-bits?
char byte = 0xff;
printf("%lu\n", sizeof(byte)) // Output is '1'
printf("%x\n", byte); // Output is 'ffffffff'
If the size of byte
is only one byte, then why does printf()
behave as if it is four bytes? 如果
byte
的大小只有一个字节,那么为什么printf()
行为就像四个字节一样?
Formally, your program exhibits undefined behavior: %x
format specification expects an argument of type unsigned int
, but you are passing an int
, as explained below (hat tip @R). 在形式上,您的程序表现出未定义的行为:
%x
格式规范需要类型为unsigned int
的参数,但是您传递的是int
,如下所述(帽子提示@R)。 This is harmless in practice on modern two's-complement machines, since int and unsigned have compatible bit layouts. 这在现代二进制补机中实际上是无害的,因为int和unsigned具有兼容的位布局。 But again, technically, this is undefined behavior and it would be a good idea to fix it, as in
printf("%x\\n", (unsigned)byte);
但同样,从技术上讲,这是未定义的行为,修复它是个好主意,如
printf("%x\\n", (unsigned)byte);
. 。
The rules for passing parameters to variadic functions state that all integral types smaller than int get promoted to int. 将参数传递给可变参数函数的规则表明,小于int的所有整数类型都被提升为int。 Otherwise, how would
printf
know, upon seeing %x
, whether to grab one byte or four bytes off the stack? 否则,在看到
%x
, printf
如何知道是否从堆栈中抓取一个字节或四个字节? From the standard: 从标准:
5.2.2p7 :
5.2.2p7:
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg(18.10)...
If the argument has integral or enumeration type that is subject to the integral promotions(4.5),
or a floating point type that is subject to the floating point promotion(4.6),
the value of the argument is converted to the promoted type before the call.当给定参数没有参数时,参数的传递方式是接收函数可以通过调用va_arg
(18.10)...
来获取参数的值(18.10)...
如果参数具有受限于的整数或枚举类型整数提升(4.5),
或浮点类型受浮点提升(4.6),
参数的值在调用之前转换为提升类型。
This is how your char
turns into an int
. 这就是你的
char
变成int
。 It's unspecified whether char
is signed or unsigned, but apparently, on the platform you use it's a signed type. 未指定
char
是签名还是未签名,但显然,在您使用它的平台上是签名类型。 So it gets sign-extended when promoted to int
. 因此,当提升为
int
时,它会进行符号扩展。 0xff
is (char)-1
, and 0xffffffff
is (int)-1
. 0xff
是(char)-1
0xffffffff
是(int)-1
。
I think it's due to integer promotion
我认为这是由于
integer promotion
A good blog post on this concept: http://www.idryman.org/blog/2012/11/21/integer-promotion/ 关于这个概念的好文章: http : //www.idryman.org/blog/2012/11/21/integer-promotion/
You have invoked Undefined Behavior by passing the wrong argument type to printf
. 您通过将错误的参数类型传递给
printf
来调用未定义的行为。 The %x
specifier requires an argument of type unsigned int
, but you passed (due to default promotions) a signed int
. %x
说明符需要unsigned int
类型的参数,但是您传递了(由于默认促销)一个signed int
。 This is arguably valid if the value of the signed int
argument is non-negative, but on your system, plain char
happens to be a signed type, so byte
contains the result of applying an implementation-defined conversion to 0xff
; 如果signed
int
参数的值是非负的,这可以说是有效的,但是在你的系统上,plain char
恰好是一个signed类型,所以byte
包含将实现定义的转换应用到0xff
; the usual result of this conversion is -1. 这种转换的通常结果是-1。
A char
is signed 8-bit. char
是8位签名的。 The "%x\\n"
format says to print an integer. "%x\\n"
格式表示打印整数。 So the value of byte
is sign extended to an integer. 所以
byte
的值是符号扩展为整数。 Since a char
of 0xff
is, in that context, an 8-bit value of -1
, printf
is just printing the hex integer value of a -1
, which is ffffffff
. 由于
char
的0xff
是,在这种情况下,一个8位的值-1
, printf
只是印刷的十六进制整数值-1
,这是ffffffff
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.