法楽日記

デジタル散策記&マインド探訪記

Cプリプロセッサのマクロ展開(置換・文字列化・結合)の処理順序

C プリプロセッサのマクロ展開の仕様を正確に理解すれば自明の結果なのでしょうが、初心者は頭を悩ませてしまいます…

マクロ展開は、(1)左辺を右辺に置換、(2)演算子「#」「##」を適用、を繰り返していると理解すればよいのかしら… また、関数形式マクロの置換は、まず引数のマクロ展開を済ませてから、関数のマクロ展開が行われると理解するとよいのかしら…

#include <stdio.h>

#define CONCAT1(a, b)   a##b
#define CONCAT2(a, b)   CONCAT1(a, b)
#define STRINGIZE1(s)   #s
#define STRINGIZE2(s)   STRINGIZE1(s)

#define FUNC1       CONCAT1(PREFIX, _func1)
#define FUNC2       CONCAT2(PREFIX, _func2)
#define FUNC3       CONCAT2(PREFIX, _func3)

#define PREFIX      abc
#define abc_func3   xyz_func3

static void FUNC1(int n) { printf("C%d: %s()\n", n, __FUNCTION__); }
static void FUNC2(int n) { printf("C%d: %s()\n", n, __FUNCTION__); }
static void FUNC3(int n) { printf("C%d: %s()\n", n, __FUNCTION__); }

int
main(int argc, char **argv)
{
    FUNC1(1);
    FUNC2(2);
    FUNC3(3);

    printf("S1: %s\n", STRINGIZE1(FUNC2));
    printf("S2: %s\n", STRINGIZE2(FUNC2));
    printf("S3: %s\n", STRINGIZE2(FUNC3));
}

出力は下記の通り。

C1: PREFIX_func1()
C2: abc_func2()
C3: xyz_func3()
S1: FUNC2
S2: abc_func2
S3: xyz_func3

Keywords: c-preprocessor, token-pasting, stringizing