Setup
我对在 C 中调用函数时的默认参数提升有几个问题。这是第 6.5.2.2 节“函数调用”第 6、7 和 8 段C99 标准 (pdf)(为了便于阅读,添加了重点并分成列表):
第 6 段
- 如果表示被调用函数的表达式的类型为不包括原型,对每个参数以及具有类型的参数执行整数提升
float
被提升为double
。这些被称为默认参数促销.
- 如果参数的数量不等于参数的数量,则行为未定义。
- 如果函数定义的类型为包括一个原型,并且原型以省略号结尾 (
, ...
) 或者提升后参数的类型与参数的类型不兼容,行为未定义。
- If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases:
- 一种提升类型是有符号整数类型,另一种提升类型是相应的无符号整数类型,并且该值可以用两种类型表示;
- 两种类型都是指向字符类型的限定或非限定版本的指针,或者
void
.
第 7 段
- 如果表示被调用函数的表达式的类型为确实包括原型,参数像通过赋值一样隐式转换为相应参数的类型,将每个参数的类型视为其声明类型的非限定版本。
- 函数原型声明符中的省略号表示法会导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是对尾随参数执行的。
第 8 段
- 没有隐式执行其他转换;特别是,参数的数量和类型不会与函数定义中的参数进行比较不包含函数原型声明符.
我知道的
- The 默认参数促销 are
char
and short
to int
/unsigned int
and float
to double
- 可变参数函数的可选参数(例如
printf
) 受到默认参数促销的影响
作为记录,我的理解函数原型这是:
void func(int a, char b, float c); // Function prototype
void func(int a, char b, float c) { /* ... */ } // Function definition
Question
我真的很难理解这一切。我有一些问题:
- 原型函数和非原型函数的行为真的有如此大的差异吗,例如在默认升级和隐式转换方面?
- 默认参数提升何时发生?总是这样吗?或者只是在特殊情况下(比如可变参数函数)?这是否取决于函数是否原型化?
支持程序员的回答——这才是真货。
对于那些想知道的人why事情是这样的:在 1988 年之前的黑暗时代,经典的“K&R”C 中不存在函数原型之类的东西,并且建立了默认参数提升,因为 (a) 本质上是“免费”的,因为它不需要任何成本。在寄存器中放入一个字节比在寄存器中放入一个字更多,并且 (b) 减少参数传递中的潜在错误。第二个原因从来没有完全解决这个问题,这就是为什么 ANSI C 中函数原型的引入是 C 语言有史以来最重要的变化。
至于默认促销活动何时开始:当参数的预期类型为unknown,也就是说,当没有原型或参数是可变参数时。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)