char byte = 0xff;
printf("%lu\n", sizeof(byte)) // Output is '1'
printf("%x\n", byte); // Output is 'ffffffff'
如果 的大小byte
只有一个字节,那么为什么printf()
表现得好像它是四个字节?
形式上,您的程序表现出未定义的行为:%x
格式规范需要一个类型的参数unsigned int
,但您传递的是一个int
,如下所述(帽子提示@R)。这在现代二进制补码机器上实际上是无害的,因为 int 和 unsigned 具有兼容的位布局。但同样,从技术上讲,这是未定义的行为,修复它是一个好主意,如printf("%x\n", (unsigned)byte);
.
将参数传递给可变参数函数的规则规定,所有小于 int 的整数类型都被提升为 int。否则,如何printf
知道%x
是从堆栈中抓取一个字节还是四个字节?从标准:
5.2.2p7:
当给定参数没有参数时,参数以接收函数可以通过调用 va_arg 获取参数值的方式(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
符需要 type 的参数unsigned int
,但您传递了(由于默认促销)签名的int
. 如果有符号参数的值是非负的,这可以说是有效的,但是在您的系统上,plain恰好是有符号类型,因此包含将实现定义的转换应用于; 这种转换的通常结果是-1。int
char
byte
0xff
Achar
是有符号的 8 位。"%x\n"
格式说打印一个整数。所以 的值byte
是符号扩展为整数。由于 a char
of是,在这种情况下,0xff
的 8 位值只是打印 a 的十六进制整数值,即。-1
printf
-1
ffffffff