Mid*_*lue 15 c type-conversion
来自C编程语言第2版:
由于函数调用的参数是表达式,因此在将参数传递给函数时也会发生类型转换.在没有函数原型的情况下,char和short变为int,float变为double.
通过阅读文本,我得到的印象是,除非您通过使用强制转换或函数原型显式指定参数类型,否则函数参数将始终作为int或double传递.
为了验证我的假设,我编译了以下代码:
#include <stdio.h>
main()
{
unsigned char c = 'Z';
float number = 3.14f;
function_call(c, number);
}
void function_call(char c, float f)
{
}
Run Code Online (Sandbox Code Playgroud)
编译后我得到以下警告:
typeconversion.c:11:警告:'function_call'的冲突类型
typeconversion.c:7:警告:'function_call'之前的隐式声明就在这里
我的猜测是c和数字都在函数调用中转换为int和double,然后转换回char和float.这是真的发生了什么?
Mic*_*man 19
演员阵容无关紧要,重要的是(可能隐含的)原型.
void foo(short s) {
// do something
}
int main(void) {
signed char c = 'a';
foo(c); // c is promoted to short by explicit prototype
bar(c); // c is promoted to int by implicit prototype
}
void bar(int i) {
// do something
}
Run Code Online (Sandbox Code Playgroud)
当书中写着"函数调用的参数是表达式"时,它意味着适用相同类型的促销规则.如果将函数参数视为对函数原型中指定的变量的隐式赋值,则可能更容易理解.例如,在foo()上面的调用中有一个隐含的short s = c.
这就是演员无关紧要的原因.请考虑以下代码段:
signed char c = 'a';
int i = (short) c;
Run Code Online (Sandbox Code Playgroud)
这里c的值首先被提升为short(显式地)然后被提升为int(隐式地).价值i总是一个int.
至于char和short成为int和float变成double,指的是隐式函数原型的默认类型.当编译器在看到函数的原型或函数定义之前看到对函数的调用时,它会自动生成原型.它默认int为整数值和double浮点值.
如果最终的函数声明与隐式原型不匹配,您将收到警告.
Tyl*_*nry 16
你已经大致了解了什么是错的,但并不完全正确.
你写的时候发生了什么事
function_call(c, number);
Run Code Online (Sandbox Code Playgroud)
编译器看到你正在调用一个它尚未见过的函数,因此必须决定它的签名应该是什么.根据您之前引用的促销规则,它将char提升为int并将float提升为double并确定签名为
function_call(int, double)
Run Code Online (Sandbox Code Playgroud)
然后当它看到
function_call(char c, float f)
Run Code Online (Sandbox Code Playgroud)
它将此解释为具有相同名称的不同函数的签名,这在C中是不允许的.它与您实际定义函数的原型不同的错误完全相同,只是在这种情况下原型是隐式的由编译器生成.
因此,正是这个规则引起了问题,但错误与实际在类型之间来回转换值没有任何关系.