简体   繁体   English

为什么printf将8位字符填充到32位?

[英]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? 否则,在看到%xprintf如何知道是否从堆栈中抓取一个字节或四个字节? 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 . 由于char0xff是,在这种情况下,一个8位的值-1printf只是印刷的十六进制整数值-1 ,这是ffffffff

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM