2009-08-11 1 views
6

私は可変数の引数をとる関数をC言語で書いています。C varargs - va_copyの問題

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

これまでのところ、とても良いです。 Right Way™のやり方を変えて、さまざまな議論をとるバージョンと、va_listという別のバージョンを作るのがベストだと決めました。

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

それほど難しくありません。 my_vprintf()は、argsを2つの異なる関数(最初にsnprintf()の長さで必要な部屋を決定するために、次にsprintf()に割り当ててから)に送信する必要があります。私はva_copyでこれを行います。

これはすべて上質でダンディーですが、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関数は1つの引数を受け取り、2つの別々のコピーが作成されるようにva_listを2回通して機能する - しかし、それらがどれほどうまくいくかはわかりません(再帰的解決法は、私はちょうどvsnprintf()に電話したいと思えば、うまくやれますか?)。

だから私はあなたに、StackOverflowユーザーを回します。私がC89との互換性を提供するために何かできることがありますか、またはva_copy__va_copy(確かにごくわずかですが)のユーザーがいなくても、それを吸い取って取る必要がありますか?

+0

2009年です。なぜC89互換性が必要なのでしょうか? – stepancheg

+0

VC++はそれをサポートしていないため(おそらくはサポートしないため)私はそれを持っているのが好きです。私はそれが良いことだと思う。 –

+0

私は、MSがレコードから実際に離れて、C99のために行くつもりはないと言っていると思いますが、顧客が望む奇妙な機能を選んで選択する点を除いては、 – KTC

答えて

3

(a)=(b)は信頼できません。でも、va_listのは何かのようにすることができますとして(パブリック関数は、単純なラッパーになり)された2 va_listを渡す:

typedef __va_list_impl va_list[1]; 

がいる1上のva_argを行うことは、他のを修正するだろう(私はSolarisは、そのような使用することを覚えているようです種類のもの、ああ、レジスタウィンドウ...)。悲しいことに、私はあなたが望むことをする確実な方法がないことを知っています。

+0

私はこれを恐れていました。しかたがない。私はhack-'va_copy'を '#error 'に変更するのが適切だと思います。新しいコンパイラを入手してください。" –

+0

この特定のケースでは、1つの配列を割り当てることができないので、va_copyマクロの代入は失敗します別のものに。 – caf