1. ホーム
  2. c

[解決済み] プリプロセッサ演算子##の応用と注意点とは?

2023-03-22 12:42:57

質問

以前の多くの質問で述べたように、私は K&R を使って作業しており、現在プリプロセッサに取り組んでいます。より興味深いことの1つは、私が以前Cを学ぼうとしたどの試みからも決して知らなかったことですが、それは ## プリプロセッサー演算子です。K&R によると

プリプロセッサー演算子 ## は、マクロ展開時に実引数を連結する方法を提供します。 を連結する方法を提供します。もし パラメータが に隣接している場合 ## に隣接している場合,そのパラメータは は実際の引数に置き換えられます。 ## とその周囲の空白が削除され が削除され,結果が再スキャンされる。 例えば、マクロ paste はその二つの引数を連結します。

#define paste(front, back) front ## back

だから paste(name, 1) はトークンを作成します。 name1 .

実世界でこれをどのように、そしてなぜ使うのでしょうか?また、考慮すべき点はありますか?

どのように解決するのですか?

CrashRpt。マクロのマルチバイト文字列をUnicodeに変換するために##を使用する。

CrashRpt(クラッシュレポートライブラリ)での面白い使い方として、以下のようなものがあります。

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
//Note you need a WIDEN2 so that __DATE__ will evaluate first.

ここでは、1文字につき1バイトの文字列ではなく、2バイトの文字列を使おうとしています。これは本当に無意味に見えるかもしれませんが、彼らは正当な理由があってこれをやっているのです。

 std::wstring BuildDate = std::wstring(WIDEN(__DATE__)) + L" " + WIDEN(__TIME__);

日付と時刻を文字列で返す別のマクロと一緒に使うのだそうです。

配置 L の隣に __ DATE __ の隣にある場合は、コンパイルエラーになります。


Windows の場合。一般的な Unicode またはマルチバイト文字列のための ## の使用

Windowsは以下のようなものを使っています。

#ifdef  _UNICODE
    #define _T(x)      L ## x
#else
    #define _T(x) x
#endif

そして _T はコードのいたるところで使われています


様々なライブラリで、アクセッサやモディファイアの名前をきれいにするために使用します。

また、アクセッサやモディファイアを定義するためにコードで使用されているのを見たことがあります。

#define MYLIB_ACCESSOR(name) (Get##name)
#define MYLIB_MODIFIER(name) (Set##name)

同様に、他のタイプの賢い名前の作成にも、この同じ方法を使うことができます。


様々なライブラリ、一度に複数の変数宣言を行うために使用します。

#define CREATE_3_VARS(name) name##1, name##2, name##3
int CREATE_3_VARS(myInts);
myInts1 = 13;
myInts2 = 19;
myInts3 = 77;