使用va_copy的目的是什么?

4
我读了一些关于C/C++中可变参数函数的内容,并在一个提到重用va_list的 线程 中发现了,为了在GCC中重用它,你需要使用 va_copy 函数并传入其副本。同时,在同一个线程中,他们建议使用以下方式定义:

#define va_copy(d,s) ((d) = (s)) 这意味着简单地将 va_list s 的值分配给 va_list d。

使用 va_list ap1 = va_list ap 不更易读吗?创建另一个名为 va_copy 的函数的目的是什么?


5
在那个帖子中建议将其定义为 ((d) = (s)) 的答案,并没有建议在GCC或通常情况下这样做。这是针对MSVC的一个具体建议。C标准定义了va_copy和相关功能必须满足的某些属性,而C实现以不同的方式实现这些属性。在MSVC支持可变参数列表的方法中,((d) = (s)) 可能有效,在其他方法中则可能无效。 - Eric Postpischil
1个回答

10
在GCC中,您需要使用带有va_copy的副本,并且在同一线程上,他们建议使用以下定义:
#define va_copy(d,s) ((d) = (s))
这意味着它只是将va_list s的值分配给va_list d。但在另一个讨论串中,J Jorgenson答案指出:在尝试重用va_list时,必须使用va_copy(),因为GCC实现会导致va_list被修改,在v??printf()函数使用后,指针会定位在最后一个参数之后。
这意味着如果您需要在GCC中制作副本,则需要使用va_copy。该回答讨论了如何实现va_copy:

A previous question about the lack of va_copy in MSVC had some decent enough suggestions, including to implement your own version of va_copy for use in MSVC:

#define va_copy(d,s) ((d) = (s))
谈论的是MSVC没有实现va_copy。添加这样一个“无用”的宏的原因是,这样您就可以在GCC和MSVC中都使用va_copy并获得正确的行为。
“va_list ap1 = va_list ap”可能不足以仅使用va_list来实现,这取决于va_list的实现方式。有些事情需要发生,而这些事情无法通过operator =完成。例如,如果va_list是指针类型,则无法为其重载operator =,因此需要创建一个命名的“函数”。

尽管措辞可能不意味着我不知道这个。我的问题是为什么不直接告诉每个人使用 va_list ap1 = ap,这样可以以更直观的方式完成相同的事情。 - R3G3N3R4T0R
@R3G3N3R4T0R,我已经对那个答案进行了补充。 - NathanOliver
由于大多数编译器无法像那样复制va_list,因此您需要使用@R3G3N3R4T0R。复制是实现定义的,并且这种赋值方式不可移植。va_copy()更具可移植性,除了MSVC,该直接赋值也被支持。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接