为什么printf将8位字符填充到32位?
char byte = 0xff; printf("%lu\n", sizeof(byte)) // Output is '1' printf("%x\n", byte); // Output is 'ffffffff'
如果byte
的大小只有一个字节,那么为什么printf()
行为就像四个字节一样?
在forms上,您的程序表现出未定义的行为: %x
格式规范需要类型为unsigned int
的参数,但是您传递的是int
,如下所述(帽子提示@R)。 这在现代二进制补机上实际上是无害的,因为int和unsigned具有兼容的位布局。 但同样,从技术上讲,这是未定义的行为,修复它是个好主意,如printf("%x\n", (unsigned)byte);
。
将参数传递给可变参数函数的规则规定,小于int的所有整数类型都会被提升为int。 否则,在看到%x
, printf
如何知道是否从堆栈中抓取一个字节或四个字节? 从标准:
5.2.2p7:
当给定参数没有参数时,参数的传递方式是接收函数可以通过调用va_arg(18.10)...
来获取参数的值(18.10)...
如果参数具有受限于的整数或枚举类型整数提升(4.5),
或浮点类型受浮点提升(4.6),
参数的值在调用之前转换为提升类型。
这就是你的char
变成int
。 未指定char
是签名还是未签名,但显然,在您使用它的平台上是签名类型。 因此在升级为int
时会进行符号扩展。 0xff
是(char)-1
0xffffffff
是(int)-1
。
我认为这是由于integer promotion
关于这个概念的好博文: http : //www.idryman.org/blog/2012/11/21/integer-promotion/
您通过将错误的参数类型传递给printf
来调用未定义的行为。 %x
说明符需要类型为unsigned int
的参数,但您传递了(由于默认促销)一个signed int
。 如果signed int
参数的值是非负的,这可以说是有效的,但是在你的系统上,plain char
恰好是一个signed类型,所以byte
包含将实现定义的转换应用到0xff
; 这种转换的通常结果是-1。
char
是8位签名的。 "%x\n"
格式表示打印整数。 所以byte
的值是符号扩展为整数。 由于0xff
的char
在该上下文中是8位值-1
,因此printf
只打印-1
的hex整数值,即ffffffff
。