2013-09-25 8 views
11

受け取る引数に応じて異なるものに展開するCプリプロセッサマクロを書く方法はありますか?Cマクロ内にプリプロセッサを条件付きで置くことはできますか?

#define foo() ??? 

/* 1 */ 
foo(name) 

/* 2 */ 
foo(_) 

望ましい結果:

/* 1 */ 
int name; 

/* 2 */ 
/*ignore*/ 

はい、私はマクロが悪知っています。私はこれを主に好奇心から求めています。

+12

マクロは素晴らしいです。 –

+2

目的を説明したり、より良い例を挙げたりできますか?パラメータはコンパイル時に固定する必要があります。つまり、2つの異なるマクロ名を使用することもできます。 – lurker

+0

@mbratch:この特定のケースでは、マクロを使用して変数のセットを定義していますが、いくつかの変数はオプションであり、定義しないでください。 2つの変数名を使うと、 'foo(a、b)'、 'foo(a、_)'、 'foo(_、b)'と ' foo(_、_) 'となります。 – hugomg

答えて

8

おそらく多段階マクロ展開を試してみてください。これはBoost preprocessor/control/if libraryによって使用される戦略です。

#define FOO_NAME 1 
#define FOO__ 2 

#define CONC(a,b) a##_##b 
#define FOO(x) CONC(FOO,x) 

Cマクロ展開で条件を確認する方法がないと思います。

私が思いつくのは、#文字列演算子を使用してマクロ引数を文字列リテラルに変換し、実行時関数を使用してチェックすることです。 (あなたは出力変数宣言したいところ。これは、しかし、あなたのケースでは動作しません。)

をたとえば、以下の版画「011」:

#define FOO(x) (strcmp("NAME", #x) ? 1 : 0) 

main() 
{ 
    printf("%d", FOO(NAME)); 
    printf("%d", FOO(1)); 
    printf("%d", FOO(2)); 
} 

は、コンパイラは、おそらくstrcmp比較を最適化しますコンパイル時には、本物のプリプロセッサ条件が利用可能であった場合よりも効率的ではありません。しかし、FOOを通常の関数にすると、より効率的になり、おそらく効率的になります。

#define FOO_name 1 
#define FOO__ 0 

#define CONC(a,b) a##_##b 

#define IF(c, t, e) CONC(IF, c)(t, e) 
#define IF_0(t, e) e 
#define IF_1(t, e) t 

#define FOO(x) IF(CONC(FOO,x), int x;,) 

FOO(name) // -> int name; 
FOO(_) // -> /*nothing*/ 

あなたは冒険を感じている場合は、簡単になど、マクロ展開を抑制する、コンマを許可するようにIFを拡張することができます、ギャビン・スミスの答えに展開するには、あなたが実際にマクロ展開内の状態を確認することができ

+0

面白いトリック!しかし、私が "1"の場合のすべての可能性を列挙する必要はありませんか?例えば、 '_'ならばマクロは何か他のものがあれば2を返します。 – hugomg

+0

元の質問にはうまくいかない、限られた回避策で回答を更新しました。 –

+0

残念ながら私の場合はランタイムテストを使用できません。私はゲームの最初の解決策が私が得る最高のものだと思っています。 – hugomg

8

ヘルパーマクロ。

上記のように、必要な名前はすべて事前に知っている必要がありますが、

関連する問題