4

たとえば、次のことが可能ですか。

#define definer(x) #define #x?
4

6 に答える 6

9

いいえ、できません。
シャープ ( #) 記号は、定義中は別の意味を持ちます。つまり、これが引数の場合は、引用符で囲んで文字列にします。

于 2009-01-09T06:19:10.190 に答える
8

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 やその他の自動化と結び付けると、非常にシームレスになり、開発につまずくことはありません。

于 2009-01-09T08:36:58.523 に答える
3

いいえ、できません。

あるマクロを別のマクロから参照することはできますが、あるマクロを別のマクロから定義することはできません。

于 2009-01-09T06:17:47.960 に答える
3

わずかに異なることを実行するために複数回呼び出すことができるプリプロセッサ コードのセグメントを作成しようとしている場合、これを行う 1 つの (ややひどい) 方法は、コードを 1 つの.hファイルに分離し、それを#include複数回実行することです。アイデアは、ファイルを「ルーチンを呼び出す」たびに、インクルードされたファイルが参照する特定のプリプロセッサ定数を#include最初に ing して「引数を渡す」ということです。#define

これが役立つと私が見た場所の 1 つは、「文字列化された」フォームとの間で変換できる「スマートな」列挙を生成する場合です (これは I/O に役立ちます)。.hたとえば、を含むファイルを作成します

ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)

#include1 回目は whereが宣言ENUMVAL()を作成するような方法で定義され、1 回目は文字列化された名前の配列を生成するような方法で が定義されます。このようにすることで、実際のトークンのリストを複数回指定する必要がなくなります。enumENUMVAL()

于 2009-01-09T09:10:41.480 に答える
2
#define definer(x) #define #x?

#x は x の文字列化です。文字列トークンを #define することはできません。(#define "foo".) 識別子[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 <stdint.h>については知っています。これは単なる例です。)

于 2009-01-09T18:50:40.943 に答える
0

あなたの構文は無効ですが、あなたの質問に対する答えは技術的にはイエスです。しかし、それは、コードを読み取れず、保守できなくする厄介なトリックによってのみ達成できます。

http://www.ioccc.org/years.html#1995_vanschnitzおよびhttp://www.ioccc.org/years.html#2004_vik2も参照してください。

于 2009-01-10T03:10:19.050 に答える