Cプリプロセッサディレクティブをネストできますか?
-
06-07-2019 - |
質問
たとえば、次の可能性があります。
#define definer(x) #define #x?
解決
構文は無効ですが、質問に対する答えは技術的にはイエスです。しかし、それはコードを読みにくく、維持できないようにする厄介なトリックによってのみ達成できます。
参照: http://www.ioccc.org/years.html#1995_vanschnitz および http://www.ioccc.org/years.html#2004_vik2
他のヒント
いいえ、できません。
定義中にポンド記号(#
)は異なる意味を持ちます。つまり、これが引数の場合は、引用符で囲んで文字列にします。
Cプリプロセッサディレクティブをネストすることはできません。幸いなことに、それはほとんど必要ありません。 そのような力が本当に必要な場合は、ほぼ確実に別の力を使う方が良いでしょう Cコンパイラにコードを渡す前に実行するプリプロセッサ。例:
sed 's/@CUSTOMER@/J. Random Person/' foo.c.in > foo.c
cc foo.c
別の便利なトリックは、トリックを単一のヘッダーファイルに分離することです。 自分で作成したプログラムによって生成されます:
./generate-trickery --greet 'J. Random Person' > foo.h
foo.hは次のようになります。
#define GREET(x) ("J. Random Person greets you, " #x)
これをMakefileまたは他の自動化と結び付けると、 かなりシームレスであり、開発の手間がかかりません。
いいえ、できません。
あるマクロを別のマクロから参照することはできますが、別のマクロを定義することはできません。
わずかに異なることを実行するために複数回呼び出すことができるプリプロセッサコードのセグメントを作成しようとしている場合、これを行うことができる1つの(ややひどい)方法は、コードを単一の.h
ファイルに分離することですその後、#include
数回。アイデアは、ファイルを#define
するたびに<!> quot;ルーチンを呼び出す<!> quot; -you <!> quot; pass arguments <!> quot;まず、インクルードファイルが参照する特定のプリプロセッサ定数をENUMVAL()
指定します。
これが便利だと思った場所の1つは、<!> quot; smart <!> quot;の生成です。 <!> quot; stringized <!> quotとの間で変換できる列挙型。フォーム(I / Oに役立ちます)。たとえば、
を含むenum
ファイルを作成します
ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)
、その後<=>このファイルを2回:1回は<=>が<=>宣言を作成するように定義され、1回は<=>が配列を生成するように定義された場合文字列化された名前。このようにすることで、実際のトークンのリストを複数回指定する必要がなくなります。
#define definer(x) #define #x?
#xはxの文字列化です。文字列トークンを#defineすることはできません。 (#define <!> quot; foo <!> quot;。)それは識別子 [a-zA-Z0-9 _] * トークンでなければなりません。
そのような#defineをネストすることはできません。 #defineに#defineを含めることはできません。
#ifブロック内に#ifを 持つことができます。
#ifdef FOO
#ifdef BAR
...
#else // BAR
...
#endif // BAR
#else // FOO
...
#endif //FOO
#ifマクロで使用できる式についてもある程度制限されています。しかし、時々それを回避できます。例:
/* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4( a,b,c,d) CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d) a ## b ## c ## d
/* Creates a typedef that's legal/illegal depending on EXPRESSION. *
* Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*". *
* (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT) \
typedef char CONCATENATE_4( static_assert____, IDENTIFIER_TEXT, \
____failed_at_line____, __LINE__ ) \
[ (EXPRESSION) ? 1 : -1 ]
プラスのようなもの:
STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );
(はい、 #include <!> lt; stdint.h <!> gt; について知っています。これは単なる例です。)