プリプロセッサ (#directive) とマクロ

ソースファイルに書き込む字句 (トークン, Tokey) は:

コメント
プリプロセッサ
宣言
式
文
関数の定義

前処理 (プリプロセッシング, Preprocessing) とは, コンパイラがアセンブリ言語に翻訳する前に, ソースファイルの一部を条件的にスキップしたり, 他のソースファイル (ヘッダファイル) を読み込んだり, マクロを置き換えるための処理で, [プリプロセッサ] (前処理指令, プリプロセッシング・ディレクティブ, Preprocessing Directive) はそのための命令を指す.

プリプロセッサは, 字句要素の中の区切り子 # で始まり, 改行で終わる. プリプロセッサで定義された定数や関数をマクロ (Macro) と呼ぶ.

プリプロセッサ:

#include <stdio.h>    揃え付けのヘッダファイル stdio.h の読み込み, /usr/include 内のファイル.

#include "myheader.h"    自らが作成したヘッダファイル myheader.h の読み込み.

#if 条件    if 文の始まり. #endif とペア.

#endif    if 文の終わり. #if とペア.

#else    if 文における分岐.

#elif 条件    if 文における分岐.

#define マクロ    マクロを定義

#undef マクロ    #define マクロで定義されたマクロを無効にする.

#ifdef マクロ    [マクロが定義されていれば] という意味. #if defined と同じ.

#ifndef マクロ    [マクロが定義されていなければ] という意味. #if !defined と同じ.

ヘッダファイルの読み込みについては, コンパイルに I オプションを付してヘッダのあるディレクトリを追加することができる:

gcc -I /path/to/directory1/ -I /path/to/directory2/ ...

この場合, 自らが作成したヘッダファイルのあるディレクトリを追加すれば, #include “myheader.h” ではなく #include <myheader.h> としても, myheader.h を読み込める.

def.h

1
2
3
4
5
6
/* def.h */
#include <math.h>

#define PI 4*atan(1.0)
#define E exp(1.0)
#define MAX(x, y) (x > y ? x : y)

preprocessing.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include "def.h"

#ifndef PI
#define PI 3.14159
#endif

#ifndef E
#define E 2.71828
#endif

int main(void){

  printf("PI = %f\n", PI);
  printf("E = %f\n", E);
  printf("max{PI, E} = %f\n", MAX(PI, E));
  printf("min{PI, E} = %f\n", -MAX(-PI, -E));
  
  return 0;
}

preprocessing.c の実行結果は:

[cactus:~/code_c/c_tuts]% ./preprocessing
PI = 3.141593
E = 2.718282
max{PI, E} = 3.141593
min{PI, E} = 2.718282

もしヘッダファイルはソースファイルと同じディレクトリの中にあれば, -I オプションを使わなくても構わない.

ヘッダファイルが別のディレクトリにある場合は, 以下の書き方が適応する:

gcc -Wall -o preprocessing preprocessing.c -Imyheader/
gcc -Wall -o preprocessing preprocessing.c -I myheader/
gcc -Wall -o preprocessing preprocessing.c -I./myheader/
gcc -Wall -o preprocessing preprocessing.c -I ./myheader/

preprocessing2.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>

int main(void){
  
  printf("LINE = %d\n", __LINE__); // 行番号
  printf("FILE = %s\n", __FILE__); // ソースファイル名
  printf("DATE = %s\n", __DATE__); // ソースファイルの変更日. mm dd yyyy の形式で出力
  printf("TIME = %s\n", __TIME__); // ソースファイルの変更時間. hh:mm:ss の形式で出力
  printf("STDC = %d\n", __STDC__); // C99 準拠のコンパイラならば 1 を出力
  
  return 0;
}

preprocessing2.c の実行結果は:

[cactus:~/code_c/c_tuts]% ./preprocessing2
LINE = 5
FILE = preprocessing2.c
DATE = Oct 11 2010
TIME = 10:08:59
STDC = 1

Previous topic

文 (Statements)

Next topic

プログラムの分割とリンク