2009-08-11 56 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