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

Why does printf pad an 8-bit char to 32-bits?

本文关键字:填充 字符 为什么 printf      更新时间:2023-10-16
char byte = 0xff;
printf("%lun", sizeof(byte)) // Output is '1'
printf("%xn", byte); // Output is 'ffffffff'

如果byte的大小只有一个字节,那么为什么printf()表现得好像是四个字节?

从形式上讲,你的程序表现出未定义的行为:%x格式规范需要一个 unsigned int 类型的参数,但你传递的是一个int,如下所述(帽子提示@R(。这在现代二进制补码机器上实际上是无害的,因为 int 和无符号具有兼容的位布局。但同样,从技术上讲,这是未定义的行为,修复它是一个好主意,就像在 printf("%xn", (unsigned)byte); .

将参数传递给可变参数函数的规则规定,所有小于 int 的整型都会提升为 int。 否则,printf怎么知道,在看到%x时,是从堆栈中抓取一个字节还是四个字节?从标准:

5.2.2p7 :
当给定参数没有参数时,参数以接收函数可以通过调用va_arg (18.10)...获取参数值的方式传递 如果参数具有受整型提升(4.5),约束的整型或枚举类型,或者受浮点提升(4.6),的浮点型,则参数的值将转换为呼叫前的升级类型。

这就是您的char变成int的方式.char是有符号还是未签名是未签名的,但显然,在您使用的平台上,它是有符号的类型。因此,当提升为int时,它会得到符号扩展。 0xff(char)-10xffffffff(int)-1

我认为这是由于integer promotion

关于这个概念的一篇很好的博客文章:http://www.idryman.org/blog/2012/11/21/integer-promotion/

通过将错误的参数类型传递给printf来调用未定义的行为。%x说明符需要类型为 unsigned int 的参数,但您(由于默认升级(传递了已签名的int。如果有符号int参数的值为非负数,这可以是有效的,但是在您的系统上,纯char恰好是有符号类型,因此byte包含将实现定义的转换应用于0xff的结果;此转换的通常结果为 -1。

char是 8 位有符号的。"%xn"格式表示打印一个整数。因此,byte的值是符号扩展为整数。由于0xffchar在这种情况下是 8 位值 -1printf只是打印-1的十六进制整数值,即ffffffff