C言語

【C言語】プリプロセッサの種類と使い方

この記事では、C言語のプリプロセッサについて解説します。

プログラム言語において プリプロセッサとは、ソースコードがコンパイラなどに渡される前に前処理を施すプログラムのことです。

C言語では以下のようなプリプロセッサが用意されています。

  • インクルード(#include)
  • デファイン(#define, #undef)
  • 条件コンパイル(#ifdef, #else, #elif, #endif, #ifndef)

それでは、1つずつ見ていきましょう!

インクルード

インクルードとは、ファイルを読み込むための機能です。

#include キーワードの後ろに <ファイル名> でファイルを指定することで標準ライブラリ(言語によってあらかじめ用意されているファイル)を読み込むことできます。

#include <ファイル名>

自作ファイルを読み込みたい場合は、"ファイル名" でファイルを指定します。

#include "ファイル名"

例えば、いつも使っている printf()関数 は、stdio.h から読み込んでいました。なので、ソースコードの #include <stdio.h> をコメントアウトして実行してみてください。

// #include <stdio.h>

int main() {

    printf("出力\n");

}

インクルードをコメントアウトした時にコンパイルするとエラーが発生します。

デファイン

ディファインとは、定数や式に名前を付ける機能です。マクロとも呼ばれます。定数や式に名前を付けることでコンパイラに渡される前にその名前が指定した定数や式に置換されます。

#define キーワードの後ろに名前を指定し、続けて定数や式を記述します。

#define 名前 定数や式

例えば、以下のように #define NUM 3 と定義することで、それ以降に記述されている NUM が 3 に置換された状態でコンパイラに渡されます。

#include <stdio.h>

#define NUM 3

int main() {

    printf("%d\n", NUM);
    
}

実行結果

3

関数形式マクロ

関数なんかも定義することができます。これは 関数マクロ と呼ばれたりします。

#define 関数名(引数) (処理)

以下のコードでは、引数を2つ取る ADD という名前の関数マクロを定義しています。

#include <stdio.h>

#define ADD(a, b) (a + b)

int main() {

    int a = 1, b = 2;

    printf("%d\n", ADD(a, b));

}

実行結果

3

複数の文を含むマクロ

複数の文を含む関数マクロは、do-while文 を使って以下のように定義します。

#define 関数名(引数) do {処理1; 処理2; ...; } while(0)

以下のコードでは、受け取った値の和を計算し、その結果を出力してくれる複数文のマクロを定義しました。

#include <stdio.h>

#define ADD_PRINT(a, b) do {int r = a  + b; printf("%d\n", r);} while(0)

int main() {

    ADD_PRINT(1, 2);

}

実行結果

3

マクロの削除

ちなみに、#undef を使うことで定義したマクロを削除できます。

#include <stdio.h>

#define NUM 3
#undef NUM

int main() {

    printf("%d\n", NUM);

}

上記コードを実行すると「NUMなんて宣言されていないよ」というエラーが発生します。#undef によって NUM を削除したのでこのようなエラーが発生しました。

条件コンパイル

条件コンパイルとは、指定したディファイン(マクロ)が定義されているかどうかで分岐し、コンパイルするコードを変更することができます。

#include <stdio.h>

int main() {

#ifdef DEBUG
    printf("デバッグ\n");
#elif TEST
    printf("テスト");
#else
    printf("本番\n");
#endif

}

実行結果

本番

コンパイルする際に -D オプションを渡すことでマクロを定義することができる。それを使うことでコンパイルするソースコードをコンパイル時に変更することができる。

ターミナル

% gcc main.c -o main -D DEBUG
% ./main                     
デバッグ

#ifndef を使うことで指定したマクロが定義されていない場合に分岐させることができる。

#include <stdio.h>

int main() {

#ifndef DEBUG
    printf("デバッグ\n");
#else
    printf("本番\n");
#endif

}

実行結果

% gcc main.c -o main -D DEBUG
% ./main                     
本番

ソースコードを書き換えることなくコンパイルするコードを変更できるため便利です。

まとめ

この記事では、C言語のプリプロセッサの種類と使い方を解説しました。

プリプロセッサを使うことでソースコードをコンパイルする前に前処理を施すことができました。コンパイルされる際には既に前処理されたソースコードが渡されるので実行ファイルの速度に影響を与えません。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

C言語おすすめ参考書
MMGames (著), 秀和システム(出版)
中山 清喬 (著), 株式会社フレアリンク (著)