Replacing text macros
プリプロセッサは、テキストマクロ置換と関数形式のテキストマクロ置換をサポートします。
目次 |
構文
#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
はトークンシーケンス
#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
内でパラメータ置換が実行され、結果を引用符で囲んで文字列リテラルを効果的に生成します。さらに、プリプロセッサは埋め込まれた文字列リテラル(もしあれば)を囲む引用符をエスケープするためにバックスラッシュを追加し、必要に応じて文字列内のバックスラッシュを二重化します。すべての先頭および末尾の空白は削除され、テキスト中間の連続する空白(ただし埋め込まれた文字列リテラル内を除く)は単一のスペースに圧縮されます。この操作は「文字列化」と呼ばれます。文字列化の結果が有効な文字列リテラルでない場合、動作は未定義です。
|
#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標準の各バージョンで増加する:
|
|
__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
に展開される
(マクロ定数) |
以下の追加のマクロ名は実装によって事前定義される場合があります:
|
__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__
は(詳細は
関数定義
を参照)、時々
|
(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
テキストマクロの置換
|