プリプロセッサ

プリプロセッサとは、Preprocessor(前処理系)つまり、C言語ではコンパイルの前に行う処理の事で、ここで処理させる命令をプリプロセッサ命令またはプリプロセッサディレクティブといいます。


プリプロセッサ命令の種類

プリプロセッサ命令は次のものがあります。

▲PageTop

ファイルの読込み

ファイルの読込みは次の命令を使用します。


#include

「#include」ディレクティブの書式は次の通りです。


Cコンパイラに用意されている標準関数のとき

#include <ファイル名>

自作関数のとき

#include "ファイル名"

・サンプルソース1(sample1301.c)

#include <stdio.h>  /* printf関数の定義ファイルを読込み */
#include "sample1301.h"  /* 構造体Bookの定義ファイルを読込み */

int main() {
    struct Book book = {"プログラミング言語C", 2800};
    printf("名前:%s\t価格:%d円\n", book.name, book.price);

    return 0;
}

・サンプルソース2(sample1301.h)

struct Book {
    char name[30];  /* 名前 */
    int  price;  /* 価格 */
};

・実行結果

C:\dev\c>sample1301 [Enter]
名前:プログラミング言語C      価格:2800円
        

▲PageTop

定数、マクロの定義

定数やマクロを定義するときは次の命令を使用します。


#define

「#define」ディレクティブの書式は次の通りです。


定数に名前を付けるとき

#define 定数名 定数

マクロを定義するとき

#define マクロ名(引数) 処理

マクロの定義で処理が複数行になる場合

#define マクロ名(引数)  処理1 \
                  処理2

・サンプルソース(sample1302.c)

#include <stdio.h>

#define CNT 10  /* 定数CNTを定義 */
#define PRINT(count) printf("%d\n", count)  /* マクロPRINT(count)を定義 */

int main() {
    PRINT(CNT);

    return 0;
}

・実行結果

C:\dev\c>sample1302 [Enter]
10
        

#undef

「#define」で定義した定数やマクロを無効にします。これにより同じ定数名やマクロ名で異なる値や処理を再定義する事が出来ます。

#undef 定数名またはマクロ名

マクロの使用上の注意

マクロを使用するにあたって、特に算術の優先順位などに関して注意する必要があります。

次に示す例のようにマクロはプリプロセッサ処理で、単に処理の置き換えを行っているに過ぎないということを覚えておいてください。


・間違い例

#include <stdio.h>

#define ADD(num1, num2) num1+num2  /* 2つの引数を足し算するマクロ */

int main() {
    printf("ADD(1, 2)*10=%d\n", ADD(1, 2)*10);  /* 加算した数を10倍する(つもり) */

    return 0;
}

・実行結果

C:\dev\c>sample1303 [Enter]
ADD(1, 2)*10=21  ← 「3*10=30」ではなく「1+2*10=21」となる。
  つまりマクロは処理の置き換えに過ぎない!!
        

・修正例(sample1303.c)

#include <stdio.h>

#define ADD(num1, num2) (num1+num2)  /* 2つの引数を足し算するマクロ計算の優先順位を考慮し”()”(括弧)で囲む */

int main() {
    printf("ADD(1, 2)*10=%d\n", ADD(1, 2)*10);  /* 加算した数を10倍する */

    return 0;
}

・実行結果

C:\dev\c>sample1303 [Enter]
ADD(1, 2)*10=30  ← 「(1+2)*10=30」となる。
        

▲PageTop

条件付コンパイル

次のディレクティブを使用することで、コンパイルする対象を制御することができます。


#if ~ #elif ~ #else ~ #endif

1. 条件が真のときコンパイルをおこなう。
#if 条件
ソースコード;
#endif

2. 条件が真のときソースコード1のコンパイルおこない、それ以外はソースコード2のコンパイルをおこなう。
#if 条件
ソースコード1;
#else
ソースコード2;
#endif

3. 条件1が真のときソースコード1のコンパイルをおこなう。条件1が偽で条件2が真のときはソースコード2のコンパイルおこなう。それ以外はソースコード3のコンパイルをおこなう。
#if 条件1
ソースコード1;
#elif 条件2
ソースコード2;
#else
ソースコード3;
#endif


#ifdef ~ #elif ~ #else ~ #endif および #ifndef ~ #elif ~ #else ~ #endif

1. 定数またはマクロが定義されている(いない)のときコンパイルをおこなう。
#ifdef(#ifndef) 定数またはマクロ
ソースコード;
#endif

2. 定数またはマクロが定義されている(いない)のときソースコード1のコンパイルおこない、それ以外はソースコード2のコンパイルをおこなう。
#ifdef(#ifndef) 定数またはマクロ
ソースコード1;
#else
ソースコード2;
#endif

3.定数1またはマクロ1が定義されている(いない)のときソースコード1のコンパイルをおこなう。定数2またはマクロ2が定義されている(いない)のときはソースコード2のコンパイルおこなう。それ以外はソースコード3のコンパイルをおこなう。
#ifdef(#ifndef) 定数1またはマクロ1
ソースコード1;
#elif 定数2またはマクロ2
ソースコード2;
#else
ソースコード3;
#endif

▲PageTop