3

アプリケーションにエラーメッセージを出力する可変引数関数があります。そのコードは次のとおりです。

void error(char *format,...)
{   va_list args;
    printf("Error: ");
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    printf("\n");
    abort(); 
}

この関数は、次のようなエラー状態で使用されます。

error("invalid image width %d and image height %d in GIF file %s",wid,hei,name);

このerror()関数は、さまざまな場所からさまざまな引数を使用して呼び出されます(可変引数関数)。

関数アプローチは正常に機能します。

さて、この関数をマクロに変換する必要がある場合、どうすればよいですか?私はそれを次のようにやってみました:

#define error(format)  {va_list args;\
    printf("Error: ");\
    va_start(args, format);\
    vfprintf(stderr, format, args);\
    va_end(args);\
    printf("\n"); abort()}

しかし、これは引数を正しく出力しません。

上記のマクロ定義の何が問題になっていますか?

修正は何ですか?

4

5 に答える 5

2

コンパイラがISOスタイルの可変個引数マクロをサポートしている場合は、次のようにマクロを定義できます。

#define error(...) \    
    fprintf(stderr, "Error: ");   \
    fprintf(stderr, __VA_ARGS__); \
    fprintf(stderr, "\n"); \
    abort();

または、GCCを使用している場合は、GNUスタイルの可変個引数マクロも使用されます。

#define error(format, args...) \    
    fprintf(stderr, "Error: ");   \
    fprintf(stderr, format , ## args); \
    fprintf(stderr, "\n"); \
    abort();

詳細については、 http: //gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.htmlを参照してください。

アップデート

コンパイラが可変個引数マクロをサポートしていない場合、(不十分な?)代替手段はva_list関数内アプローチに固執することです。定義をヘッダーファイルに配置したい場合は、おそらく静的インライン関数ですか?

static inline void error(const char *fmt, ...) {
#define PRINT_ERROR
    va_list args;
    fprintf(stderr, "Error: "); 
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    fprintf(stderr, "\n");
    abort();
#endif
}
于 2009-08-25T12:14:40.990 に答える
1

これは、マクロで使用される可変引数に関するいくつかの例を含む記事です。それはあなたが探していることをするはずのようです。__VA_ARGS__マクロで使用できます。

どのコンパイラを使用していますか?

于 2009-08-25T12:11:37.680 に答える
0

マクロは(まだ?)可変個引数をサポートしていません。とにかく、ここでは使用できません。可変個引数関数va_listの引数でのみ機能します。

とにかく関数(あなたによると正常に動作します)をマクロに置き換えたいのはなぜですか?

于 2009-08-25T12:09:16.780 に答える
0

多くのコンパイラは、次のようなGNUスタイルの可変個引数マクロをサポートしています。

#define error(format,args...) do { \
  fprintf(stderr, "error: " format "\n", ##args); \
  abort(); \
} while(0)

ただし、移植性を目指す場合は、可変個引数マクロを使用しないでください。

于 2009-08-25T12:13:24.013 に答える
0

あなたが望むことをする一般的な拡張機能があります、単に書いてください:

#define error(args...) (fputs("Error: ",stdout),printf(args),puts(""))

C99ユーザーは次のようにも言うことができます:

#define error(...) (fputs("Error: ",stdout),printf(__VA_ARGS__),puts(""))

ただし、の使用にはいくつかの問題__VA_ARGS__があります。幸い、それに対処するためのGCC拡張機能がありますが、その後、コンパイラー固有の拡張機能を使用するようになり、args...モードはより広く利用可能になります。

于 2009-08-25T12:15:10.957 に答える