C 函数中的变量参数

Posted

技术标签:

【中文标题】C 函数中的变量参数【英文标题】:Variable arguments in C functions 【发布时间】:2017-10-20 11:01:56 【问题描述】:

我读过关于可变参数函数“int func(int, ...)”的文章。 这些函数的参数在哪里分配(堆栈或堆)?

因为我读到va_end() 宏释放了分配给va_list 的空间,所以“释放”这个词引起了我的注意。

注意:我知道常规函数会进入堆栈,但这种类型的函数很有趣,因为参数的数量是未知的。

我只想确定它不像没有预定义空间的数组; 最后我们使用malloc()free()

链接:https://www.tutorialspoint.com/cprogramming/c_variable_arguments.htm

【问题讨论】:

通常变量参数被压入堆栈,就像常规参数一样。您不必担心mallocfree 我只是想确定它不像没有预定义空间的数组:数组总是有一个预定义的空间。 它有什么不同? 【参考方案1】:

c 本身并没有指定诸如“堆”或“堆栈”之类的东西,因此编程标准和可移植c,您应该更好地考虑c 标准的类别:静态、自动和动态存储。

尽管如此,在典型的实现中,“自动存储”转换为“堆栈用于它”。函数参数就是这种情况,可变参数函数也不例外。

va_end() 可能释放一些动态存储(通常:在堆上分配)的原因是va_arg() 宏通常需要一些上下文信息来查找 next 参数。 va_start() 将为该信息分配内存(而不是为参数本身)并以某种方式对其进行初始化,以便第一个 va_arg() 调用返回第一个可变参数。

请注意,va_start() 的实现没有分配内存。 va_list 的定义方式可能是为所需的上下文信息提供空间。但这对作为程序员的你根本不感兴趣,所有va_* 的东西对你来说都是一个黑匣子,如果文档声明“调用@987654331 @当清理完成时”,你就这样做;)

【讨论】:

【参考方案2】:

通常平台有一个调用约定。前几个参数进入寄存器,后面的参数进入堆栈。这对 C 代码本身是故意不透明的。 va_start 和 va_end 提供了一个围绕该调用约定的包装器,以允许您按索引而不是按名称顺序访问参数。

请注意,您不能在运行时构建 va_args 块。这是 C 不允许你做的少数几件事之一。您只能通过调用变量 args 函数来生成块。

还要注意,实际上变量 args 列表用于包装对 vsprintf() 的调用。您几乎不会发现它们在生产 C 代码中用于任何其他目的。

【讨论】:

以上是关于C 函数中的变量参数的主要内容,如果未能解决你的问题,请参考以下文章

使用 C/C++ 中的派生类成员变量将参数传递给 Base 构造函数

C语言基础:作用域规则(局部变量,全局变量,形式参数)全局变量与局部变量在内存中的区别初始化局部变量和全局变量

c语言中结构体变量做函数参数的问题

C语言的两个问题: 所有的递归程序均可以用非递归算法实现?递归函数中的形式参数是自动变量吗? c语言中

在 Python 函数中使用可变函数参数来模仿类 C 的静态变量

在OD 反汇编关于EBP 和ESP 局部变量 和函数参数 区别 比如: