6

可変数の引数を取る関数をCで書いています。

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

ここまでは順調ですね。RightWay™を実行して、可変引数をとるバージョンと、をとる別のバージョンを作成するのが最善であると判断しましたva_list

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

それほど難しいことではありません。ただし、2つの異なる関数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-1つの引数を食べて再帰する関数、2つを渡してva_list2つの別々のコピーが作成されるなど-しかし私はそれらがどれほどうまくいくかわかりません(そして再帰的な解決策はうまくいきません電話をかけたいだけならvsnprintf()、今、そうしますか?)

だから私はあなたに目を向けます、StackOverflowユーザー。C89との互換性を提供するために私ができることは他にありますか、それともユーザーはva_copyそれ__va_copyを吸い込んで受け入れる必要がありますか?

4

1 に答える 1

3

(a)=(b)信頼できません。va_listva_list は次のようになるため、2 つを渡すこともできます (パブリック関数は単純なラッパーになります)。

typedef __va_list_impl va_list[1];

一方にva_argを実行すると、もう一方が変更されます(Solarisはそのようなものを使用していることを覚えているようです、ああ、レジスタウィンドウ...)。悲しいことに、私はあなたが望むことをする確かな方法を知りません.

于 2009-08-11T09:45:00.123 に答える