c - 为什么在 C 中不允许使用 void f(...)?

标签 c variable-length

为什么 C 不允许具有可变长度参数列表的函数,例如:

void f(...)
{
    // do something...
}

最佳答案

我认为要求可变参数函数必须具有命名参数的动机是为了 va_start 的统一性。为了便于实现,va_start 采用最后一个命名参数的名称。使用典型的可变参数调用约定,并根据存储的方向参数,va_arg 将在地址 (¶meter_name) + 1(first_vararg_type* )(¶meter_name) - 1,加上或减去一些填充以确保对齐。

我认为语言不能支持不带命名参数的可变参数函数没有任何特别的原因。必须有一种替代形式的 va_start 用于此类函数,它必须直接从堆栈指针获取第一个可变参数(或者迂腐的帧指针,这实际上是堆栈指针在函数入口处的值,因为函数中的代码很可能在函数入口后移动了 sp)。这在原则上是可能的——任何实现都应该在某种程度上以某种方式访问​​堆栈[*]——但对于一些实现者来说这可能很烦人。一旦了解可变参数调用约定,通常无需任何其他特定于实现的知识即可实现 va_ 宏,这需要知道如何直接获取调用参数.我之前在仿真层中实现了那些可变参数宏,这会让我很恼火。

此外,没有命名参数的可变参数函数没有太多实际用途。可变参数函数没有语言特性来确定可变参数的类型和数量,因此被调用者无论如何都必须知道第一个可变参数的类型才能读取它。所以你不妨把它做成一个有类型的命名参数。在 printf 和 friend 中,第一个参数的 告诉函数可变参数的类型 是什么,以及它们有多少。

我想理论上被调用者可以查看一些全局变量来弄清楚如何读取第一个参数(以及是否有一个参数),但这非常讨厌。我当然不会特意支持它,添加新版本的 va_start 会增加额外的实现负担是我的做法。

[*] 或者如果实现不使用堆栈,则无论它使用什么来传递函数参数。

关于c - 为什么在 C 中不允许使用 void f(...)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6570447/

相关文章:

c++ - 在 C++ 的可变长度函数中,将默认值参数放在何处?

c - 使用 SDL2 & Glew,尝试在 OpenGL 中绘制一个简单的白色正方形。只会黑屏

javascript - Javascript 是否可以使用可变长度数组

c - 警告...已定义但未使用 - 我真的需要 .c 文件吗?

c - fwprintf() "%ff"格式

encoding - 使用统一格式的指令有什么好处?

c++ - 为什么可变长度数组不是 C++ 标准的一部分?

java - 查找 ArrayList 中所有值的长度

C头文件循环

c - 当表达式作为 c 中的参数传递时,结果存储的类型是什么