1

在 C 语言中,当调用的函数没有原型时,编译器会执行默认参数提升。

但是C++呢?默认参数提升何时发生?

在 C++11 标准 5.2.2/7 中:

当给定参数没有参数时,参数的传递方式使得接收函数可以通过调用 va_arg (18.10) 获取参数的值。[注意:本段不适用于传递给函数参数包的参数。函数参数包在模板实例化(14.5.3)期间扩展,因此每个这样的参数在实际调用函数模板特化时都有一个对应的参数。—end note ] 对参数表达式执行左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 标准转换。具有(可能是 cv 限定的)类型 std::nullptr_t 的参数被转换为类型 void* (4.10)。在这些转换之后,如果参数没有算术、枚举、指针、指向成员的指针,或类类型,程序格式错误。传递具有非平凡复制构造函数、非平凡移动构造函数或非平凡析构函数的类类型(第 9 条)的潜在评估参数,没有相应的参数,由实现定义的语义有条件地支持。如果参数具有受整数提升 (4.5) 约束的整数或枚举类型,或受浮点提升 (4.6) 约束的浮点类型,则在调用之前将参数的值转换为提升的类型. 这些提升称为默认参数提升。没有对应的参数,有条件地支持实现定义的语义。如果参数具有受整数提升 (4.5) 约束的整数或枚举类型,或受浮点提升 (4.6) 约束的浮点类型,则在调用之前将参数的值转换为提升的类型. 这些提升称为默认参数提升。没有对应的参数,有条件地支持实现定义的语义。如果参数具有受整数提升 (4.5) 约束的整数或枚举类型,或受浮点提升 (4.6) 约束的浮点类型,则在调用之前将参数的值转换为提升的类型. 这些提升称为默认参数提升。

本段仍然没有指定默认参数提升何时发生。这一段可能讲的太多,没有清晰的逻辑。我努力概述逻辑但失败了。我不熟悉调用 va_arg

希望你能帮助我。

4

2 回答 2

1

默认促销将在调用上下文中调用函数之前发生。

如果您真的要询问执行默认促销的情况,摘录中已经介绍了这一点,尽管它是一个很小的部分,很容易错过:“当给定参数没有参数时......”。换句话说,它本质上与 C 中的情况相同,只是在 C++ 中根本不存在未指定参数类型的 C 风格函数声明。因此,唯一可以在没有参数指定其类型的情况下使用参数的情况是当函数具有显式省略号时,例如printf: int printf(char const *format, ...);

于 2013-06-28T05:53:29.397 回答
1

从您在问题中引用的那一段中:“参数的值在调用之前转换为提升的类型”

你说 C“当被调用的函数没有原型时默认参数提升”——但请记住,C++ 中不存在这种情况——你不能调用没有看到任何声明或定义的函数。

提到“调用 va_arg”意味着在调用函数时应用了一些参数提升,然后将使用va_arg函数访问值(参见http://linux.die.net/man/3/va_arg)。可以这样想:一个函数调用可能会传递 value int(3),另一个int(7777),还有另一个char(7)- 被调用函数应该如何知道会发生什么?它可能会将该参数的所有值提升为某种最大支持的整数类型,例如intor long,然后在va_arg函数中使用时,它将从int或转换为调用指定long的任何整数类型。va_arg这确实意味着,例如,该int(7777)值可能会在只有一个char是预期的,并且该值可能会在没有警告的情况下被截断为 8 位,但这通常比程序崩溃要好,因为传递的数据字节数与消耗的数量不匹配,或者其他一些奇怪的副作用。

于 2013-06-28T05:56:06.113 回答