【问题标题】:Why are parameters promoted when it comes to a variadic function?当涉及到可变参数函数时,为什么要提升参数?
【发布时间】:2021-05-13 06:05:45
【问题描述】:

当涉及到可变参数函数时,为什么要提升参数,例如浮点数被提升为 double ext,它们是按什么顺序提升的?

Variadic arguments - cppreference.com

默认转化次数

当调用可变参数函数时,在左值到右值、数组到指针和函数到指针conversions 之后,作为变量参数列表一部分的每个参数都会经历额外的转换,称为 默认参数提升:

【问题讨论】:

  • “为什么” 的大多数答案是 “因为标准是这样说的”...
  • 是的,但为什么啊哈哈
  • @Jarod42 不同意。标准不是作为神圣的启示给予我们的,而是作为工程师的协作创建的,并且在那里做出的大多数决定都是可以解释的。
  • 我认为问题是:标准有这样的要求的理由是什么。很可能是性能和内存对齐,但这需要更精确的解释或至少链接到解释这一点的论文。
  • 我尝试通过 open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdfjslint.com/chistory.html 进行筛选。唯一值得一提的是For compatibility with past practice, all argument promotions occur as described in K&R in the absence of a prototype declaration。为什么“过去的做法”会引发争论,历史上更好的人将不得不挖掘。

标签: c++ language-lawyer


【解决方案1】:

为什么要提升参数

因为这是指定语言的方式。

您可能会想,为什么要这样指定语言。我不知道这个选择是否有公开的理由,但我怀疑答案很简单:因为 C 语言就是这样指定的

你可能会想,为什么 C 语言是这样指定的。有一个标准文档 N1256 讨论了 C99 标准的一些选择的设计原理。它似乎没有涵盖这个选择。此外,C语言早在标准化之前就已经存在,C99甚至不是第一个标准版本。这种行为可能在委员会参与之前就已经存在。

不管怎样,同样的提升规则也适用于调用尚未声明的函数(C99 之前)或通过未声明参数的原型调用固定参数函数:

// this is C lanugage
void fun();

int main(int, char [][]) {
    float f = 42;
    fun(f); // argument promotes to double

    undeclared(f); // ill-formed since C99
                   // argument promotes to double prior to C99

这样做的原因可能类似于在可变参数列表的情况下提升的原因。

【讨论】:

    【解决方案2】:

    增加可变参数函数的参数使处理它们变得更加容易。由于函数代码无法从函数签名中知道参数的实际类型,因此调用必须通过其他方式传达类型,并且提升在不牺牲灵活性的情况下减少了选项的数量。

    例如,考虑可变参数函数的经典示例 - printf。当你给它%f 参数时,它已经知道这个参数是双精度的,因为它会被提升。如果没有提升,则必须存在两种不同的修饰符,一种用于单精度,另一种用于双精度。

    另一个例子是积分促销。目前任何类型都可以使用%d 修饰符,虽然短版本的修饰符确实存在,但不需要使用它们,并且可以简化它们的代码。

    此外,它在使用其他一些可变参数函数时减少了意外。例如,Posix open 函数显示为好像它是具有 2 个或 3 个参数的重载函数,最后一个参数在 man 中指定为 mode_t 类型。事实上,C 中没有重载,因此open 没有两个版本 - 只有一个,即可变参数。

    如果没有促销,则必须确保在使用 3 参数版本时,最后一个参数恰好是 mode_t 类型,这将非常不方便,违反直觉并且不这样做可能会导致非常意外行为。自动促销使我们免于这样做。

    【讨论】:

    • 但是有格式说明符用于窄类型,例如%hu 用于unsigned shorthhi 用于signed char
    • 我在标准中没有提到它们的实施不是强制性的。
    • 如何将 %u 与 unsigned short 一起使用,从而意外地以 %u 打印一个带符号的 int?
    • 嗯,我不认为函数需要担心这些类型。而是va_arg 宏。我从未实现过它,但我想当大多数小类型在调用方提升时,它就不会是 PITA 了。
    • @eerorika hh 是从 C99 开始新添加的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2016-07-15
    • 2016-07-27
    • 1970-01-01
    • 2018-10-02
    • 2013-01-09
    相关资源
    最近更新 更多