为什么我可以在C中将整数隐式转换为字符

为什么我可以在C中将整数隐式转换为字符,c,casting,integer,char,C,Casting,Integer,Char,我想知道,为什么在C语言中可以从整数隐式转换为字符 例如,如果: int i = 2789; printf("%c\n",i); 将返回一个字符,因为它将截断从最重要的位开始的位。 但通常情况下,如果这意味着您将失去精度,您就无法真正进行隐式转换,那么为什么我可以在这里执行此操作?这里没有进行隐式转换 printf是一个可变函数,这意味着在调用函数之前,char类型的任何参数都会转换为int。您的参数已经是int类型,因此不会发生转换。传递给函数的所有整型参数通常都会提升到CPU的字大小,因

我想知道,为什么在C语言中可以从整数隐式转换为字符

例如,如果:

int i = 2789;

printf("%c\n",i);
将返回一个字符,因为它将截断从最重要的位开始的位。
但通常情况下,如果这意味着您将失去精度,您就无法真正进行隐式转换,那么为什么我可以在这里执行此操作?

这里没有进行隐式转换


printf
是一个可变函数,这意味着在调用函数之前,
char
类型的任何参数都会转换为
int
。您的参数已经是
int
类型,因此不会发生转换。

传递给函数的所有整型参数通常都会提升到CPU的字大小,因此无论您传递的是
char
short
int
还是
long
,都是如此,进入
printf
后,堆栈和/或寄存器的物理布局仍然相同

因此,没有“演员阵容”,只有正常的参数传递


然而,这并不是说代码是正确的。参数传递和类型提升是在ABI中定义的,而不是由C定义的,因此它可能无法在所有平台上工作。(尽管它在绝大多数情况下都能工作。)

如果您在上有警告,我猜它会警告您
printf
无论如何都会升级为整数(因此没有强制转换),并且编译器无法根据格式字符串中的说明符检查类型。从编译器的角度来看,因为这里没有不匹配,因为(换句话说)它不认为参数
i
必须是
char
@mbrach:许多现代编译器(包括GCC)对
printf
类函数有特殊处理,确实会检查格式字符串并找到
%c
@Dolda2000啊好的,我没意识到!谢谢。从技术上讲,参数不是转换为
int
s,而是转换为CPU字号。例如,在x86-64上,它们被提升为64位,即使
int
s的长度为32位。@Dolda2000:变量函数的参数经历默认参数提升,包括整数提升。整数提升表示小于
int
的任何内容都将转换为
int
(或
无符号int
,视情况而定)。在C标准中没有“CPU字大小”的概念。啊,没错。我想,事实上,在这种情况下,两件事都在进行:
int
变量函数的提升,以及整数参数传递的字数提升。当然,后者是由特定于平台的ABI而不是C标准定义的。@Dolda2000:可能吧。但是,如果在ABI级别上有字数提升,那么这在C语言的范围内是“看不见的”。至少对于用严格且正确的C语言编写的程序是看不见的。我想这是真的,
int
promotion在这里起作用,然而,这意味着问题中的程序是正确的,并且从严格C的角度来看是定义良好的,尽管这与我最初的假设相反。这是真的。(至少,只要你写的是“比字号大的任何类型”)请看我在回答下面的评论。此外,C标准规定了类型提升。ABI只是定义了物理实现的方式。