Namespaces
Variants

Replacing text macros

From cppreference.net

プリプロセッサは、テキストマクロ置換と関数形式のテキストマクロ置換をサポートします。

目次

構文

#define 識別子 置換リスト  (オプション) (1)
#define 識別子  ( パラメータ ) 置換リスト (2)
#define 識別子  ( パラメータ , ... ) 置換リスト (3) (C99以降)
#define 識別子  ( ... ) 置換リスト (4) (C99以降)
#undef 識別子 (5)

説明

#define ディレクティブ

#define ディレクティブは identifier をマクロとして定義します。つまり、コンパイラに対して identifier の後続するすべての出現を replacement-list で置き換えるよう指示します。これはオプションで追加処理される可能性があります。識別子が既に何らかの種類のマクロとして定義されている場合、定義が同一でない限りプログラムは不適格となります。

オブジェクト形式マクロ

オブジェクト形式マクロは、定義された identifier のすべての出現を replacement-list で置き換えます。 #define ディレクティブのバージョン(1)は、まさにこのように動作します。

関数形式マクロ

関数形式マクロは、定義された identifier の各出現箇所を replacement-list で置き換え、さらにいくつかの引数を取り、それらの引数が replacement-list 内の対応する parameters の出現箇所を置き換えます。

関数形式マクロの呼び出しの構文は、関数呼び出しの構文と類似しています:マクロ名の各インスタンスの直後に次の前処理トークンとして(が続く場合、それが置換リストによって置換されるトークン列の開始を示します。このシーケンスは対応する)トークンによって終了し、中間にある一致する左右の括弧のペアをスキップします。

引数の数は、マクロ定義内の引数( parameters )の数と同じでなければならず、そうでない場合プログラムは不適格となります。識別子が関数形式ではない場合、つまり自身の後に括弧がない場合は、一切置換されません。

#define ディレクティブのバージョン (2) は、単純な関数形式マクロを定義します。

#define ディレクティブのバージョン (3) は、可変長引数を持つ関数形式マクロを定義します。追加の引数は __VA_ARGS__ 識別子を使用してアクセスでき、この識別子は置換対象の識別子に指定された引数で置き換えられます。

#define ディレクティブのバージョン (4) は、可変長引数を持つ関数形式マクロを定義しますが、通常の引数は持ちません。引数は __VA_ARGS__ 識別子でのみアクセス可能であり、これはその後、置換対象の識別子に指定された引数で置き換えられます。

バージョン(3,4)では、 replacement-list はトークンシーケンス __VA_OPT__ ( content ) を含むことができ、これは __VA_ARGS__ が空でない場合に content に置き換えられ、それ以外の場合は何も展開されません。

#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
F(a, b, c) // replaced by f(0, a, b, c)
F()        // replaced by f(0)
#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
G(a, b, c) // replaced by f(0, a, b, c)
G(a, )     // replaced by f(0, a)
G(a)       // replaced by f(0, a)
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
SDEF(foo);       // replaced by S foo;
SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };
(C23以降)


注意: 関数形式マクロの引数に、対応する左右の括弧で保護されていないカンマ(例えば macro ( array [ x = y, x + 1 ] ) atomic_store ( p, ( struct S ) { a, b } ) ; )が含まれている場合、そのカンマはマクロ引数の区切り文字として解釈され、引数の数が合わないためにコンパイルエラーが発生します。

# および ## 演算子

関数形式マクロにおいて、 # 演算子を識別子の前に置くと、 replacement-list 内でパラメータ置換が実行され、結果を引用符で囲んで文字列リテラルを効果的に生成します。さらに、プリプロセッサは埋め込まれた文字列リテラル(もしあれば)を囲む引用符をエスケープするためにバックスラッシュを追加し、必要に応じて文字列内のバックスラッシュを二重化します。すべての先頭および末尾の空白は削除され、テキスト中間の連続する空白(ただし埋め込まれた文字列リテラル内を除く)は単一のスペースに圧縮されます。この操作は「文字列化」と呼ばれます。文字列化の結果が有効な文字列リテラルでない場合、動作は未定義です。

# __VA_ARGS__ の前に現れる場合、展開された __VA_ARGS__ 全体が引用符で囲まれます:

#define showlist(...) puts(#__VA_ARGS__)
showlist();            // expands to puts("")
showlist(1, "x", int); // expands to puts("1, \"x\", int")
(C99以降)

任意の2つの連続する識別子の間に ## 演算子が存在する場合、 replacement-list 内で2つの識別子に対してパラメータ置換を実行し、その結果を連結します。この操作は「連結」または「トークン貼り付け」と呼ばれます。有効なトークンを形成するトークンのみが貼り付け可能です:より長い識別子を形成する識別子、数値を形成する数字、あるいは + = += を形成する演算子などです。 / * を貼り付けてもコメントは作成できません。なぜなら、コメントはマクロ置換が考慮される前にテキストから除去されるためです。連結の結果が有効なトークンでない場合、動作は未定義です。

注意: 一部のコンパイラは、カンマの後かつ ## の前に __VA_ARGS__ が出現することを許可する拡張機能を提供しています。この場合、 __VA_ARGS__ が空でないときは ## は何も行いませんが、 __VA_ARGS__ が空のときはカンマを削除します。これにより、 fprintf ( stderr , format, ##__VA_ARGS__) のようなマクロを定義することが可能になります。

# および ## 演算子の評価順序は未規定です。

#undef ディレクティブ

#undef ディレクティブは identifier の定義を解除します。つまり、 #define ディレクティブによる identifier の以前の定義を取り消します。identifierに関連付けられたマクロが存在しない場合、このディレクティブは無視されます。

定義済みマクロ

以下のマクロ名は任意の翻訳単位で事前に定義されています:

__STDC__
整数定数 1 に展開される。このマクロは準拠した実装を示すことを意図している
(マクロ定数)
__STDC_VERSION__
(C95)
long 型の整数定数に展開され、その値はC標準の各バージョンで増加する:
  • 199409L (C95)
  • 199901L (C99)
  • 201112L (C11)
  • 201710L (C17)
  • 202311L (C23)
    (マクロ定数)
__STDC_HOSTED__
(C99)
実装がホスト環境(OS上で実行)の場合、整数定数 1 に展開され、フリースタンディング環境(OSなしで実行)の場合、 0 に展開される
(マクロ定数)
__FILE__
現在のファイル名を文字列リテラルとして展開する。 #line ディレクティブで変更可能
(マクロ定数)
__LINE__
ソースファイルの行番号を整数定数として展開する。 #line ディレクティブで変更可能
(マクロ定数)
__DATE__
翻訳日付を「Mmm dd yyyy」形式の文字列リテラルとして展開する。月名は asctime で生成されるものと同じで、日が10未満の場合「dd」の最初の文字はスペースになる
(マクロ定数)
__TIME__
翻訳時刻を「hh:mm:ss」形式の文字列リテラルとして展開する。 asctime ( ) で生成される時刻と同じ形式
(マクロ定数)
__STDC_UTF_16__
(C23)
char16_t がUTF-16エンコーディングを使用することを示すために 1 に展開される
(マクロ定数)
__STDC_UTF_32__
(C23)
char32_t がUTF-32エンコーディングを使用することを示すために 1 に展開される
(マクロ定数)
__STDC_EMBED_NOT_FOUND__ __STDC_EMBED_FOUND__ __STDC_EMBED_EMPTY__
(C23)
それぞれ 0 1 2 に展開される
(マクロ定数)

以下の追加のマクロ名は実装によって事前定義される場合があります:

日本語訳: 変更点: - `(macro constant)` → `(マクロ定数)` - その他のテキスト(`expands to`, `if`, `use UTF-32 encoding`)はC++の専門用語およびコード内のテキストとして翻訳せず保持
__STDC_ISO_10646__
(C99)
yyyymmL 形式の整数定数に展開される。 wchar_t がUnicodeを使用する場合、この日付はサポートされているUnicodeの最新リビジョンを示す
(マクロ定数)
__STDC_IEC_559__
(C99) (C23で非推奨)
IEC 60559がサポートされている場合 1 に展開される
(マクロ定数)
__STDC_IEC_559_COMPLEX__
(C99) (deprecated in C23)
IEC 60559複素数演算がサポートされている場合に 1 に展開される
(マクロ定数)
__STDC_UTF_16__
(C11)
UTF-16エンコーディングを使用する場合に 1 に展開される
(マクロ定数)
__STDC_UTF_32__
(C11)
expands to 1 if char32_t use UTF-32 encoding
(macro constant)
__STDC_UTF_32__
(C11)
expands to 1 if char32_t use UTF-32 encoding
(マクロ定数)
__STDC_MB_MIGHT_NEQ_WC__
(C99)
1 に展開される。これは、 'x' == L 'x' が基本文字セットのメンバーに対して偽となる可能性がある場合(例えば、Unicodeを wchar_t に使用するEBCDICベースのシステムなど)
(マクロ定数)
__STDC_ANALYZABLE__
(C11)
解析可能性がサポートされている場合に 1 に展開される
(マクロ定数)
__STDC_LIB_EXT1__
(C11)
境界チェックインターフェースがサポートされている場合、 整数定数 201112L に展開される
(マクロ定数)
__STDC_NO_ATOMICS__
(C11)
アトミック型および アトミック 操作ライブラリがサポートされていない場合に 1 に展開される
(マクロ定数)
__STDC_NO_COMPLEX__
(C11)
複素数型と complex types および complex math library がサポートされていない場合に 1 に展開される
(マクロ定数)
__STDC_NO_THREADS__
(C11)
スレッドサポートが利用できない場合に 1 に展開される
(マクロ定数)
__STDC_NO_VLA__
(C11)
次の場合に 1 に展開される: 可変長配列 および可変修正型 (C23まで) 自動記憶域期間の (C23以降) がサポートされていない場合
(マクロ定数)
__STDC_IEC_60559_BFP__
(C23)
IEC 60559 バイナリ浮動小数点演算がサポートされている場合 202311L に展開される
(マクロ定数)
__STDC_IEC_60559_DFP__
(C23)
IEC 60559 10進浮動小数点演算がサポートされている場合 202311L に展開される
(マクロ定数)
__STDC_IEC_60559_COMPLEX__
(C23)
IEC 60559 複素数演算がサポートされている場合に 202311L に展開される
(マクロ定数)
__STDC_IEC_60559_TYPES__
(C23)
IEC 60559交換および拡張型がサポートされている場合 202311L に展開される
(マクロ定数)

これらのマクロの値( __FILE__ および __LINE__ を除く)は翻訳単位全体を通じて一定です。これらのマクロの再定義または未定義化を試みると未定義動作を引き起こします。

定義済み変数 __func__ は(詳細は 関数定義 を参照)、時々 __FILE__ __LINE__ と一緒に使用されるにもかかわらず(例: assert による使用)、プリプロセッサマクロではありません。

(C99以降)

#include <stdio.h>
// make function factory and use it
#define FUNCTION(name, a) int fun_##name(int x) { return (a) * x; }
FUNCTION(quadruple, 4)
FUNCTION(double, 2)
#undef FUNCTION
#define FUNCTION 34
#define OUTPUT(a) puts( #a )
int main(void)
{
    printf("quadruple(13): %d\n", fun_quadruple(13));
    printf("double(21): %d\n", fun_double(21));
    printf("%d\n", FUNCTION);
    OUTPUT(billion); // note the lack of quotes
}

出力:

quadruple(13): 52
double(21): 42
34
billion

不具合報告

以下の動作変更に関する欠陥報告書は、以前に公開されたC規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
DR 321 C99 基本文字集合において L 'x' == 'x' が常に成り立つか不明確であった 目的のために __STDC_MB_MIGHT_NEQ_WC__ が追加された

参考文献

  • C23規格 (ISO/IEC 9899:2024):
  • 6.10.4 マクロ置換 (p: 187-184)
  • 6.10.9 定義済みマクロ名 (p: 186-188)
  • C17規格 (ISO/IEC 9899:2018):
  • 6.10.3 マクロ置換 (p: 121-126)
  • 6.10.8 定義済みマクロ名 (p: 127-129)
  • C11規格 (ISO/IEC 9899:2011):
  • 6.10.3 マクロ置換 (p: 166-173)
  • 6.10.8 定義済みマクロ名 (p: 175-176)
  • C99規格 (ISO/IEC 9899:1999):
  • 6.10.3 マクロ置換 (p: 151-158)
  • 6.10.8 定義済みマクロ名 (p: 160-161)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.8.3 マクロ置換
  • 3.8.8 定義済みマクロ名

関連項目

C++ ドキュメント for テキストマクロの置換