プリプロセスを追う (#define による字句置き換え、#if)

プリプロセスで行われる主な用途として #include を見てきました。ここでは を見ていきます。

#define による字句置き換え

まずは作成しているソースコードに #define を増やしてみます。 Visual Studio で ConsoleApplication1.cpp を開きます 下記の強調部分を追加します
#include <stdio.h>
#include "MySource.h"

#define MYDEFINE 100
int myFunc();

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
    printf("MYDEFINE: %d\n", MYDEFINE);
}

int myFunc()
{
    return 123;
}
[ローカル Windows デバッガー] を押下します。 ビルドとしてはエラーになりますが、プリプロセスには成功するので問題ありません。 [ソリューション エクスプローラー] のプロジェクト項目を右クリック > [エクスプローラーでフォルダーを開く] を押下します [Debug] フォルダを開きます "ConsoleApplication1.i" を開きます ファイルの最下部までスクロールし、下記のような出力となっていることを確認します
#pragma warning(pop) 
#line 2449 "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.22000.0\\ucrt\\stdio.h"
#pragma external_header(pop)
#line 2 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\ConsoleApplication1.cpp"
#line 1 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\MySource.h"
#pragma once
int mySourceFunc();
int mySourceFunc1(int);
int mySourceFunc2(int, int);
#line 3 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\ConsoleApplication1.cpp"


int myFunc();

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
    printf("MYDEFINE: %d\n", 100);
}

int myFunc()
{
    return 123;
}
.i ファイルではあたかも初めからソースコードに 100 が記述されていたかのようになっています。また、元の #define は消えてなくなっています。これが #define による字句置き換えです。ソース上の #define がすべて置き換わった後のこのテキストファイルに対して、コンパイラはコンパイル処理を行います。"プリプロセス" (処理) というのは、コンパイル処理からみて事前に行われる処理であることからそのように呼ばれています。
【備考】マクロについて 例えば下記のような書き方をすると、引数を用いた字句置き換えができます :
#define MYDEFINE(num) (100+num)
これをマクロといいます。この資料での詳細な説明は省略します。

#if ~ #endif による有効/無効の切り替え

"ConsoleApplication1.cpp" を開きます 下記の強調部分を追加します
#include <stdio.h>
#include "MySource.h"

#define MYDEFINE 100
int myFunc();

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
    printf("MYDEFINE: %d\n", MYDEFINE);
#if MYDEFINE >= 100
    printf("#define MYDEFINE は 100 以上です\n");
#endif
}

int myFunc()
{
    return 123;
}
[ローカル Windows デバッガー] を押下します。 ビルドとしてはエラーになりますが、プリプロセスには成功するので問題ありません。 [ソリューション エクスプローラー] のプロジェクト項目を右クリック > [エクスプローラーでフォルダーを開く] を押下します [Debug] フォルダを開きます "ConsoleApplication1.i" を開きます ファイルの最下部までスクロールし、次のような出力が含まれていることを確認します
int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
    printf("MYDEFINE: %d\n", 100);

    printf("#define MYDEFINE は 100 以上です\n");
#line 18 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\ConsoleApplication1.cpp"
}
今回は MYDEFINE >= 100 を満たしているため、該当の行が有効化されています。 では次に、下記を書き換えてみます
#define MYDEFINE 99
同じ要領で再度 .i ファイルを更新し、開いてみてください
int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
    printf("MYDEFINE: %d\n", 99);


#line 18 "D:\\User\\Desktop\\ConsoleApplication1\\ConsoleApplication1\\ConsoleApplication1.cpp"
}
該当の行が無効化されており、.i ファイルから消えていることが確認できました。 このページはこれで終わりです。このページでは を確認しました。
このページで "ConsoleApplication1.cpp" に追加した行はこの後は不要となります。このページの確認が完了しましたら下記の通り削除します。
#include <stdio.h>
#include "MySource.h"

#define MYDEFINE 99
int myFunc();

int main()
{
    printf("Hello World!\n");
    printf("myFunc: %d\n", myFunc());
    printf("mySourceFunc: %d\n", mySourceFunc());
    printf("mySourceFunc1: %d\n", mySourceFunc1(20));
    printf("mySourceFunc2: %d\n", mySourceFunc2(1,30));
    printf("MYDEFINE: %d\n", MYDEFINE);
#if MYDEFINE >= 100
    printf("#define MYDEFINE は 100 以上です\n");
#endif
}

int myFunc()
{
    return 123;
}