#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
STR3 == "s1"を連結することは可能ですか?これを行うには、argsを別のマクロ関数に渡します。しかし、直接的な方法はありますか?
#define STR1 "s"
#define STR2 "1"
#define STR3 STR1 ## STR2
STR3 == "s1"を連結することは可能ですか?これを行うには、argsを別のマクロ関数に渡します。しかし、直接的な方法はありますか?
回答:
両方が文字列の場合は、次のようにできます。
#define STR3 STR1 STR2
プリプロセッサは隣接する文字列を自動的に連結します。
編集:
以下に示すように、連結を行うのはプリプロセッサーではなくコンパイラーです。
L"a"
し"b"
て取得することはできませL"ab"
んが、連結L"a"
してL"b"
取得しますL"ab"
。
文字列リテラルは言語レベルで連結されているので、このようなソリューションは必要ありません。「s」「1」は有効なプリプロセッサトークンではないため、とにかく機能しません。
[編集:残念ながらいくつかの賛成票を受け取った以下の誤った「記録のための」コメントへの応答として、私は上記のステートメントを繰り返し、プログラムの断片が
#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")
gccの前処理フェーズからこのエラーメッセージが生成されます。
]
ただし、一般的なトークンの貼り付けについては、これを試してください:
/*
* Concatenate preprocessor tokens A and B without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define PPCAT_NX(A, B) A ## B
/*
* Concatenate preprocessor tokens A and B after macro-expanding them.
*/
#define PPCAT(A, B) PPCAT_NX(A, B)
次に、たとえば両方 PPCAT_NX(s, 1)
とPPCAT(s, 1)
識別子を生成s1
しない限り、s
ケースたマクロとして定義され、PPCAT(s, 1)
生成<macro value of s>1
。
テーマの続きはこれらのマクロです:
/*
* Turn A into a string literal without expanding macro definitions
* (however, if invoked from a macro, macro arguments are expanded).
*/
#define STRINGIZE_NX(A) #A
/*
* Turn A into a string literal after macro-expanding it.
*/
#define STRINGIZE(A) STRINGIZE_NX(A)
そして、
#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"
対照的に、
STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"
#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"
"s""1"
C(およびC ++)では有効です。これらは2つのトークン(文字列リテラル)であり、コンパイラーはそれ自体を連結し、1つのトークンとして脅迫します。
"s""1" isn't a valid token
-それは正しいです。あなたが言うように、それは2つのトークンです。しかし、それらを##で結合すると、2つのトークンではなく単一の前処理トークンになるため、コンパイラーは連結を行わず、レクサーがそれらを拒否します(言語には診断が必要です)。
STRINGIZE_NX(whatever occurs here)
ため、何が発生したか、またはここでのマクロ定義に関係なく、「ここで発生したもの」に展開されます。
if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"
-それは誤りであり、あなたのテストに似ていません。あなたはこれを理解したり正しく理解したりしないように一生懸命努力しています、そして私はあなたにこれ以上応答しません。
ヒント:上記のSTRINGIZE
マクロはすばらしいですが、間違いがあり、その引数がマクロではない場合-名前にタイプミスがあるか#include
、ヘッダーファイルを忘れた場合、コンパイラーは意図したマクロ名をエラーのない文字列。
への引数STRINGIZE
が常に通常のC値を持つマクロであることを意図している場合、
#define STRINGIZE(A) ((A),STRINGIZE_NX(A))
一度展開して有効性を確認し、それを破棄してから、もう一度文字列に展開します。
なぜ私が含まれていなかったのかでSTRINGIZE(ENOENT)
は"ENOENT"
なく、なぜ終わるのかを理解するのにしばらく時間がかかりました。"2"
errno.h
,
オペレーターの適切な使用のための+1 。:)
((1),"1") "." ((2),"2")
単に "1" "。" "2"ではなくのようなシーケンスになります)
STRINGIZE
定義では"The value of ENOENT is " STRINGIZE(ENOENT)
機能"The value of ENOENT is" STRINGIZE_EXPR(X)
するが、エラーを生成する。