我已经阅读了关于变量参数函数" int func(int, ...)
"。
这些函数的参数在哪里被分配(堆栈或堆)?
因为我读到va_end()
宏释放了分配给va_list
的空间,所以单词"释放"引起了我的注意。
注意:我知道常规函数会转到堆栈,但这种类型的函数很有意思,因为参数的数量是未知的。
我只是想知道它不像没有预先定义空间的数组;
我们最后使用malloc()
和free()
。
链接:https://www.tutorialspoint.com/cprogramming/c_variable_arguments.htm
答案 0 :(得分:2)
c本身没有指定“堆”或“堆栈”之类的东西,因此编程标准和可移植的c,你应该更好地考虑c标准的类别:静态,自动和动态存储。
然而,在典型的实现中,“自动存储”转换为“堆栈用于它”。这是函数参数的情况,可变参数函数在这里也不例外。
va_end()
可能释放某些动态存储(通常:在堆上分配)的原因是va_arg()
宏通常需要一些上下文信息来查找 next 参数。 va_start()
将为该信息分配内存 (不是参数本身)并以某种方式对其进行初始化,以便第一个va_arg()
调用返回第一个可变参数。
请注意,va_start()
的实现没有来分配内存。 va_list
可能以某种方式定义,它为所需的上下文信息提供空间。但是作为程序员,你应该根本不感兴趣,所有va_*
内容都是黑盒子,如果文档说明“call完成清理时va_end()
“,你就这样做了;)
答案 1 :(得分:0)
通常平台都有调用约定。前几个参数进入寄存器,后续的参数进入堆栈。这对C代码本身是故意不透明的。 va_start和va_end提供了一个调用约定的包装器循环,允许您按索引而不是按名称依次访问参数。
请注意,您无法在运行时构建va_args块。这是C不允许你做的少数几件事之一。您只能通过调用变量args函数来生成块。
另请注意,实际上变量args列表用于包装对vsprintf()的调用。你几乎从未发现它们在生产C代码中用于任何其他目的。