3

免責事項:マクロ値の文字列化に似た質問への回答はすでに見ました。

次のテスト プログラムを検討してください。

#include <stdio.h>
#define QUOTE(str) #str
#define EXPAND_AND_QUOTE(str) QUOTE(str)

#define MACRO HelloWorld

int main() {
    printf("%s\n", EXPAND_AND_QUOTE(MACRO));
    printf("%s\n", QUOTE(MACRO));

    #undef MACRO
    printf("%s\n", EXPAND_AND_QUOTE(MACRO));
    printf("%s\n", QUOTE(MACRO));
}

このプログラムの出力は次のとおりです。

HelloWorld
MACRO
MACRO
MACRO

望ましい出力は

HelloWorld
MACRO

MACRO

マクロ(つまり、MACRO ではないメタマクロ) を再定義して、目的の出力を得る方法はありますか?

特に、3番目printfが次と同等であることを望んでいます。

printf("%s\n", QUOTE());

つまり、未定義のマクロを「無」に展開し、その「無」を引用関数に渡したいのです。

4

5 に答える 5

2

これを試して:

#undef MACRO
#define MACRO

または:

#undef MACRO
#ifndef MACRO
#  undef EXPAND_AND_QUOTE
#  define EXPAND_AND_QUOTE(str) ""
#endif
于 2013-10-25T23:18:48.243 に答える
1

#undef MACRO試す代わりに:

#undef MACRO
#define MACRO \0

\0 は、MACRO を渡すことができることを保証しますが (一部のコンパイラはVC++がないとMACROを解析できないため)、依然として空白の文字列です。\0 は文字列の ASCII 末尾のエスケープ文字であり、本質的に MACRO を空白文字列に設定します。

于 2013-10-25T23:25:44.243 に答える
-1

これは、次の 2 つの注意事項で実行できます。

  • コンパイラは可変長マクロをサポートする必要があります (C99 標準の一部でした)。
  • 0,マクロ トークンを定義するときに追加する必要があります。つまり、

    #define MACRO 0, HelloWorld
    

上記を考えると、RESOLVE私が思いついたこの気の利いたマクロを使用できます。これは1行のバージョンです(より防弾/移植可能にすることができます):

#define RESOLVE(token, default_token, ...) default_token

ここでは、サンプル コードに適用されます。

    #include <stdio.h>

#define BLANK

#define RESOLVE(token, default_token, ...) default_token

#define QUOTE(str) #str
#define QUOTE0(str) QUOTE(str) // need the intermediate QUOTE0 function here or else you get output like `RESOLVE(0, HelloWorld, , )` instead of `HelloWorld`
#define EXPAND_AND_QUOTE(str, ...) QUOTE0(RESOLVE(str, BLANK, __VA_ARGS__)) // the BLANK token is optional here, can also be a literal blank

#define MACRO 0, HelloWorld

int main() {
    printf("%s\n", EXPAND_AND_QUOTE(MACRO));
    printf("%s\n", QUOTE(MACRO));

#undef MACRO
    printf("%s\n", EXPAND_AND_QUOTE(MACRO));
    printf("%s\n", QUOTE(MACRO));
}

コンパイルしてテストすると、出力は確かに

HelloWorld
MACRO

MACRO

仕組みRESOLVE_

基本的な考え方は、プリプロセッサは定義されたトークンと未定義のトークンを区別できませんが (未定義のトークンと通常のテキストを区別しないため)、少なくとも関数のようなマクロのパラメーター リスト内では、単一のトークンとタプルを区別できます。 . __VA_ARGS__ 次に、マクロがこの区別に基づいて異なる動作を生成できるようにします。

2 つの定義済みトークンがあるとします。

#define BAR bar
#define BAZ baz0, baz1

および未定義の token FOO。これらを に渡すとRESOLVE、効果的に展開されます

RESOLVE(FOO, BLANK) -> RESOLVE(token=, default_token=BLANK, __VA_ARGS__=)         -> BLANK
RESOLVE(BAR, BLANK) -> RESOLVE(token=bar, default_token=BLANK, __VA_ARGS__=)      -> BLANK
RESOLVE(BAZ, BLANK) -> RESOLVE(token=baz0, default_token=baz1, __VA_ARGS__=BLANK) -> baz1

の場合、 はBAZBLANKに格納されている 2 番目の値によって名前付きパラメータ リストの末尾から (省略記号の中に) 押し出されBAZ、それが返されます。

于 2016-07-07T20:59:19.827 に答える