2009-08-11 78 views
6

我在C中写了一个函数,它带有可变数量的参数。C可变参数-Va_copy问题

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,使两个单独的副本等 - 但我不知道他们将如何工作(和递归解决方案赢得'如果我只想打电话给vsnprintf(),那么现在呢?)。

所以我转向你,StackOverflow用户。有没有更多的事情可以做,以提供C89的兼容性,或者是没有va_copy__va_copy(承认很少和很远)的用户将不得不把它吸入并采取它?

+0

这是2009年。为什么你仍然需要C89的兼容性? – stepancheg 2009-08-11 09:26:53

+0

因为VC++没有(也可能不会)支持它。我喜欢拥有它。我认为这是一件好事。 – 2009-08-11 09:35:05

+0

我认为MS实际上已经有记录表明他们没有打算去购买C99,除了挑选客户想要的奇特功能。 – KTC 2009-08-11 09:50:03

回答

3

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

typedef __va_list_impl va_list[1]; 

为这一个做的va_arg将修改其他(我似乎记得的Solaris使用这样的那种东西啊,注册窗口......)。可悲的是,我知道没有办法做你想做的事。

+0

我很害怕这个。好吧。我想适当的做法是将我的hack-'va_copy'改为'#error“获取一个新的编译器”' – 2009-08-11 09:47:52

+0

在这种特殊情况下,va_copy宏中的赋值失败,因为你不能分配一个数组到另一个。 – caf 2009-08-11 11:50:04