我想编写一个返回类型为va_list的函数。
例如:va_list MyFunc(va_list args);
这种写法是否安全且可移植?
我想编写一个返回类型为va_list的函数。
例如:va_list MyFunc(va_list args);
这种写法是否安全且可移植?
va_list
可能(但不保证)是一个数组类型,因此您不能按值传递或返回它。看起来像这样的代码可能只是传递/返回指向第一个元素的指针,因此您可以在被叫方使用参数,但可能会对原始参数产生影响。va_list
可能是一个实体类型而非值类型。您可以使用 va_copy
进行复制,而不是通过赋值或函数参数/返回进行复制。虽然您肯定可以返回
这样的值,但我不确定返回值是否可以以有用的方式使用。
由于处理va_list
需要特殊处理(在va_start()
和va_copy()
之后需要va_end()
),而且va_start/copy
和va_end
宏甚至允许包含{ }
来强制执行此配对,因此您不能单独调用其中一个。
va_copy
用于创建第二个va_list
对象,它可以独立于原始对象进行读取。由于这里不需要这样做,因此可以传递和返回va_list
对象。此外,标准没有提到va_start()
和va_end()
必须在同一范围内,因此我不明白它们如何能包含{
。 - Lindydancerva_copy
使用 alloca
等技巧,因为新列表不会存在于函数返回之后。 - Steve Jessop无论语言标准如何规定,实际上这种方法不太可能奏效。一个 va_list
很可能是指向调用者在堆栈上为被调用者放置的调用记录的指针。一旦被调用者返回,该堆栈上的内存就可以被重新使用。
返回类型 va_list
不太可能实际上将列表内容复制回调用者。虽然这是 C 的有效实现,如果标准要求这样做,那么这将是规范的缺陷。
va_end
宏存在的原因正是因为va_list
不一定只是指向堆栈上的某个指针。否则,va_end
将始终是无操作的。存在这样的实现,其中在堆上分配了va_list
对象。 - Dietrich Eppva_end
与寄存器窗口或仅允许一次迭代的旧实现有关。我调整了我的答案,但这只是相对重点的问题... 大多数架构不使用堆栈来处理可变参数。 - PotatoswatterMyFunc
是否修改原始列表。我肯定遇到过两种方式都可以工作的实现。 - supercatva_list
的指针传递给函数,因此如果va_list
是一个简单的指针,则会传递指向该指针的指针,并且函数会修改原始指针所指向的内容。 - Armaliva_list
是一个数组,这种类型的参数 本质上 会被传递为指针,而在其他系统上则不是这样,但我现在看到,在你的特定情况下,你将 *
包含在参数类型中,因此它将被传递为单级间接指针(指向 va_list
中包含另一个指针的任何内容)。 - supercat
va_list
,修改它,然后在从函数返回时使用已修改的va_list
,那么最好考虑将指向va_list
的指针传递给MyFunct()
并通过指针对列表进行操作。标准特别提到了这种技术在脚注中是可行的。 - Michael Burrva_list
不是一个好的想法。通常有更安全的更好的解决方案。因此,我会认真思考并得到更好的解决方案来设计和实现函数。 - Ed Heal