为什么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。 否则,在看到%xprintf如何知道是否从堆栈中抓取一个字节或四个字节? 从标准:

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的值是符号扩展为整数。 由于0xffchar在该上下文中是8位值-1 ,因此printf只打印-1的hex整数值,即ffffffff