设置
我有关于在C语言中调用函数时默认参数提升的一些问题。下面是C99标准(pdf)第6.5.2.2节的第6、7和8段文字(已加粗并分为列表以便阅读):
第6段
- 如果表示被调用函数的表达式具有不包括原型的类型,则对每个参数执行整数提升,并将类型为
float
的参数提升为double
类型。这些被称为默认参数提升。- 如果参数数量不等于参数数量,则行为未定义。
- 如果使用包括原型的类型来定义函数,并且原型以省略号结尾(
, ...
)或者提升后参数的类型与参数的类型不兼容,则行为未定义。- 如果使用不包括原型的类型来定义函数,并且提升后的参数类型与提升后的参数类型不兼容,则行为未定义,除以下情况:
- 一个提升类型是带符号整数类型,另一个提升类型是相应的无符号整数类型,并且该值可以用两种类型表示;
- 两个类型都是指向限定或不限定版本字符类型或
void
的指针。
第7段
- 如果表示被调用函数的表达式具有包括原型的类型,则参数会被隐式转换,就像通过赋值一样,转换为相应参数的类型,将每个参数的类型视为其声明类型的未限定版本。
- 函数原型声明符中的省略号表示参数类型转换在最后一个声明的参数后停止。默认参数提升会执行到尾部参数上。
第8段
- 没有其他隐式转换执行;特别地,在不包括函数原型声明符的函数定义中,不比较参数的数量和类型与参数的数量和类型。
我知道的事情
- 默认参数提升是将
char
和short
提升为int
/unsigned int
,将float
提升为double
- 可变参数函数(如
printf
)的可选参数受默认参数提升的影响
记录一下,我对于函数原型的理解是:
void func(int a, char b, float c); // Function prototype
void func(int a, char b, float c) { /* ... */ } // Function definition
问题
我对这一切的理解非常困难。以下是我的一些问题:
- 原型函数和非原型函数的行为真的有很大差异吗,例如在默认提升和隐式转换方面?
- 默认参数提升是什么时候发生的?总是这样吗?还是只有特殊情况(如可变参数函数)?这是否取决于一个函数是否被原型化?