我正在学习默认参数提升,但在某个点上卡住了。在 C 2011(ISO/IEC 9899:2011)中,相关部分似乎是:
§6.5.2.2 函数调用
如果表示所调用函数的表达式具有不包括原型的类型,则对每个参数执行整数提升,并将类型为 float 的参数提升为 double。这些被称为默认参数提升。如果参数的数量不等于参数的数量,则行为未定义。如果使用包含省略号 (,...) 的原型结束,或者在提升后的参数类型与参数类型不兼容的情况下定义该函数,则行为未定义。如果使用不包括原型的类型定义该函数,并且在提升后的参数类型与提升后的参数类型不兼容,则行为未定义,以下情况除外:
- 一个提升的类型是有符号整数类型,另一个提升的类型是相应的无符号整数类型,并且值在两种类型中都可表示; - 两种类型都是字符类型或 void 的限定或非限定版本的指针。
在段落的最后三行中,它谈到了不包括原型的函数类型在定义时。它说如果“提升后的参数类型与提升后的参数类型不兼容,则行为未定义”。
现在我有一个非常愚蠢的疑问,即如果函数声明和函数定义都不包括原型,就像本段落中所述,那么在最后三行中他们谈论哪些参数。而“参数提升”是什么意思,因为我只学过“参数提升”。这里的“参数提升”是什么意思?
此外,您可以举例说明上述例外情况吗?如果有人能用适当的示例解释这一点,那将非常可赞赏。
§6.5.2.2 函数调用
如果表示所调用函数的表达式具有不包括原型的类型,则对每个参数执行整数提升,并将类型为 float 的参数提升为 double。这些被称为默认参数提升。如果参数的数量不等于参数的数量,则行为未定义。如果使用包含省略号 (,...) 的原型结束,或者在提升后的参数类型与参数类型不兼容的情况下定义该函数,则行为未定义。如果使用不包括原型的类型定义该函数,并且在提升后的参数类型与提升后的参数类型不兼容,则行为未定义,以下情况除外:
- 一个提升的类型是有符号整数类型,另一个提升的类型是相应的无符号整数类型,并且值在两种类型中都可表示; - 两种类型都是字符类型或 void 的限定或非限定版本的指针。
在段落的最后三行中,它谈到了不包括原型的函数类型在定义时。它说如果“提升后的参数类型与提升后的参数类型不兼容,则行为未定义”。
现在我有一个非常愚蠢的疑问,即如果函数声明和函数定义都不包括原型,就像本段落中所述,那么在最后三行中他们谈论哪些参数。而“参数提升”是什么意思,因为我只学过“参数提升”。这里的“参数提升”是什么意思?
此外,您可以举例说明上述例外情况吗?如果有人能用适当的示例解释这一点,那将非常可赞赏。
int
。 - wildplasserprintf()
的例子。我传递了一个int
,但函数期望一个double
。整数与浮点数不兼容,因此会发生UB,因为默认参数转换不会将int
转换为我们想要的double
,而是保持不变。在add_shorts
的例子中,参数提升传递了一个与short
(函数所期望的)二进制兼容的int
,因此没有UB。 - DarkAtomint
而不是double
),那么这将被视为未定义行为。这是未定义行为,因为编译器无法知道函数需要什么参数(这些信息既不包含在K&R函数中,也不包含在可变参数省略号中)。 - DarkAtom