別のマクロに渡された引数を操作するマクロを定義するにはどうすればよいでしょうか?具体的には、次の点を考慮してください:
#define PRINT(a) printf(#a": %d", a) #define PRINT_ALL(...) ? ? ? THE PROBLEM ? ? ?
望ましい使用法:
int a = 1, b = 3, d = 0; PRINT_ALL(a,b,d);
型破りな回避策を使用すると、C で再帰マクロが可能になります。目標は、次のような MAP マクロを作成することです:
#define PRINT(a) printf(#a": %d", a) MAP(PRINT, a, b, c) /* Apply PRINT to a, b, and c */
評価されないマクロ呼び出しに似たものを出力する方法を作成することから始めます:
#define MAP_OUT
次のマクロを検討します:
#define A(x) x B MAP_OUT (x) #define B(x) x A MAP_OUT (x)
評価中A(何とか) はテキストを生成します:
blah B (blah)
B (何とか) 呼び出しはこの段階では単なるテキストであるため、プリプロセッサはここで再帰を検出しません。このテキストをプリプロセッサにフィードバックすると、それが展開されます。
blah blah A (blah)
この出力を再度評価すると、A (まあまあ) マクロが展開され、再帰が完了します。このプロセスは、出力が再びプリプロセッサにフィードバックされるまで続きます。
複数の評価を容易にするために、EVAL マクロを使用してマクロ呼び出しのチェーンに引数を渡します。
#define EVAL0(...) __VA_ARGS__ #define EVAL1(...) EVAL0 (EVAL0 (EVAL0 (__VA_ARGS__))) #define EVAL2(...) EVAL1 (EVAL1 (EVAL1 (__VA_ARGS__))) #define EVAL3(...) EVAL2 (EVAL2 (EVAL2 (__VA_ARGS__))) #define EVAL4(...) EVAL3 (EVAL3 (EVAL3 (__VA_ARGS__))) #define EVAL(...) EVAL4 (EVAL4 (EVAL4 (__VA_ARGS__)))
Eachレベルは前任者の努力を増幅し、最終的に入力を 365 回評価します。たとえば、EVAL(A(何とか)) は、何とかの 365 コピーを生成し、その後に未評価の B (何とか) が続きます。このセットアップは、特定のスタック深さ制限内での再帰の基礎を提供します。
次のハードルは、再帰をいつ終了するかを決定することです。
MAP_END マクロを次のように定義します。リストの終わりのマーカー:
#define MAP_END(...)
このマクロを評価しても何も行わず、
2 つのマクロのどちらかを選択するには、リスト項目を特別なリスト終了マーカー () と比較する MAP_NEXT を使用します。
#define MAP_GET_END() 0, MAP_END #define MAP_NEXT0(item, next, ...) next MAP_OUT #define MAP_NEXT1(item, next) MAP_NEXT0 (item, next, 0) #define MAP_NEXT(item, next) MAP_NEXT1 (MAP_GET_END item, next)
MAP_NEXT は、リスト項目と次の項目に基づいて続行または停止します。一致する場合は MAP_END を返し、そうでない場合は次のパラメータを返します。
これらのコンポーネントを使用して、A と B の使用可能なバージョンを構築できます。
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__) #define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__)
これらのマクロは、操作 f を現在のリスト項目 x に適用し、次のリスト項目であるピークを調べて、続行するかどうかを決定します。
最後に、トップレベルの MAP マクロですべてを組み立てます。
#define MAP(f, ...) EVAL (MAP1 (f, __VA_ARGS__, (), 0))
このマクロは、リストの最後に () マーカーを追加し、全体を EVAL に渡します。
コードは、便宜上、GitHub のライブラリとして利用できます。
以上がC で別のマクロに渡された引数で動作するマクロを定義するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。