设置
我对在 C 中调用函数时的默认参数提升有几个问题。这是C99 标准 (pdf)中的第 6.5.2.2 节“函数调用”第 6、7 和 8 段(强调添加并分解为列表以便于阅读):
第 6 段
- 如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有类型的参数
float
提升为double
。这些被称为默认参数提升。- 如果参数的数量不等于参数的数量,则行为未定义。
- 如果函数使用包含原型的类型定义,并且原型以省略号 (
, ...
) 结尾,或者提升后的参数类型与参数类型不兼容,则行为未定义。- 如果函数定义的类型不包含原型,并且提升后的参数类型与提升后的参数类型不兼容,则行为未定义,但以下情况除外:
- 一种提升类型是有符号整数类型,另一种提升类型是对应的无符号整数类型,并且值可以在两种类型中表示;
- 这两种类型都是指向字符类型或
void
.
第 7 段
- 如果表示被调用函数的表达式具有包含原型的类型,则参数将隐式转换为相应参数的类型,就像通过赋值一样,将每个参数的类型作为其声明的非限定版本类型。
- 函数原型声明器中的省略号会导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是在尾随参数上执行的。
第 8 段
- 没有隐式执行其他转换;特别是,参数的数量和类型不会与不包含函数原型声明符的函数定义中的参数的数量和类型进行比较。
我知道的
- 默认参数提升是
char
andshort
toint
/unsigned int
andfloat
todouble
- 可变参数函数的可选参数(如
printf
)受默认参数提升的约束
作为记录,我对函数原型的理解是这样的:
void func(int a, char b, float c); // Function prototype
void func(int a, char b, float c) { /* ... */ } // Function definition
问题
我很难理解这一切。以下是我的一些问题:
- 原型化函数和非原型化函数的行为真的有很大不同吗,例如在默认提升和隐式转换方面?
- 默认参数提升何时发生?总是这样吗?或者只是在特殊情况下(比如可变参数函数)?它是否取决于函数是否原型化?