代码如下:
#include<stdio.h>
void f(unsigned char v)
{
char c = v;
unsigned char uc = v;
printf("%%X: %X, %X\n", c, uc);
}
int main(int argc, char *argv[])
{
f(0x80);
return 0;
}
结果:
%X: FFFFFF80, 80
我很困惑。 FFFFFF80
怎么来的。我们知道 char
类型包含 1 个字节。我知道 char
和 unsigned char
之间的区别在于它们处理最高位的方式,但两者都保存一个字节。
而且我认为该程序不涉及任何转换过程。
如果 c
的类型是 int
(将 unsigned char 转换为 int),符号位将扩展。但在这种情况下,它是 unsigned char
转换为char
,但都保存一个字节。
那么为什么 printf("%X",c)
的结果包含 4 个字节?
最佳答案
printf
是一个可变参数函数,它被定义为:
int printf(const char * fmt, ...);
也就是说,printf
不知道您传递给它的参数类型,它依赖于格式字符串来推断参数类型。
格式字符串后的每个参数都受到整数提升(char
被提升为 int
)。
所以 printf
在你的情况下接收到的是一个格式字符串 ("%%X: %X, %X\n"
),一个 int
包含 -128
(因为 0x80
在二进制补码架构上表示为 char
是 -128
)和一个包含 128
的 int
。
引用资料:
ISO C § 6.3.1.1:
If an
int
can represent all values of the original type, the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions.
ISO C § 6.5.2.2:
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type
float
are promoted todouble
. These are called the default argument promotions.The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.
附言
值得注意的是,您遇到的二进制补码行为是实现定义的,即 (char)0x80
不能保证等于 -128
在所有平台上。
关于c - printf char type in base16 出现混淆现象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44194546/