6

我正在用 C 语言编写一个带有可变数量参数的函数。

size_t myprintf(char *fmt, ...);

到现在为止还挺好。我决定最好以正确的方式做事,并制作一个带有可变参数的版本,以及另一个带有va_list.

size_t myprintf(char *fmt, ...);
size_t myvprintf(char *fmt, va_list args);

没那么难做到。除了my_vprintf()需要将其发送args到两个不同的函数(首先到snprintf()长度为 0 来确定我们需要多少空间,然后sprintf()在我们分配了那么多空间之后)。我用va_copy.

size_t myvprintf(char *fmt, va_list args)
{
    va_list args2;
    va_copy(args, args2);
    // do stuff with args2
    va_end(args2);
    // do more stuff with args
}

这一切都很好而且很花哨,但是 C99 的实现有点糟糕。如果可能的话,我希望我的代码也能在 C89 中工作,并与尽可能多的编译器和尽可能多的平台一起工作。我目前#include <stddef.h>在任何代码之后但之前有这个:

#ifndef va_copy
# ifdef __va_copy
#  define va_copy(a,b) __va_copy(a,b)
# else /* !__va_copy */
#  define va_copy(a,b) ((a)=(b))
# endif /* __va_copy */
#endif /* va_copy */

我被引导相信这((a)=(b))是不可靠的,我也许应该使用memcpy()或类似的东西,但这仍然是“如果你不支持 C99,我希望它有效”而不是“如果你不支持C99,永远不要害怕”(这就是我想要的)。有什么好的方法可以绕过这个限制吗?我已经看到了一些解决方案 -va_list吃一个参数并递归的函数,传递va_list两次以便制作两个单独的副本,等等 - 但我不知道它们会如何工作(递归解决方案不会做好吧,如果我只想打电话vsnprintf(),现在,会吗?)。

所以我求助于你,StackOverflow 用户。我还能做些什么来提供 C89 兼容性,还是没有用户(诚然很少va_copy__va_copy相差甚远)只是不得不将其吸入并接受它?

4

1 回答 1

3

(a)=(b)不可靠。即使传递两个va_list是(公共函数将是一个简单的包装器),因为 va_list 可以是这样的:

typedef __va_list_impl va_list[1];

为此在一个上执行 va_arg 将修改另一个(我似乎记得 Solaris 使用这种东西,啊,寄存器窗口......)。可悲的是,我不知道有什么方法可以做你想做的事。

于 2009-08-11T09:45:00.123 回答