7-1 プリプロセッサ命令とは

この記事は約5分で読めます。

プリプロセッサ命令

プリプロセッサ命令とはコンパイル前にコンパイラに対して特定の処理をさせる命令です。代表的なプリプロセッサ命令を2つ紹介します。プリプロセッサ命令は、コンパイラに対する命令なので、C言語の文法は適用されません。プリプロセッサ命令を使用する際は、#を付けて1行に記述します。

#include

#include指令は、その命令文を指定したファイルの内容に置き換えるという意味です。これをインクルードするといいます。主に関数のプロトタイプ宣言を書いたヘッダファイルをインクルードする時に使います。ヘッダファイルには拡張子.hをつけるのが一般的です。ただし、必ずしもヘッダーファイルをインクルードしないといけないという意味ではなく、他のソースファイルなどをインクルードすることも可能です。

#include <ファイル名>
#include "ファイル名"

#include指令には二通りの書き方があります。標準ライブラリの関数が含まれるファイルの場合は山括弧<>でくくります。この時処理系があらかじめ用意しているヘッダファイルの中から探します。それに対して、プログラマ自身が作ったヘッダファイルをインクルードするときはダブルクォーテーションで囲みます。

#include <stdio.h>
int main(void){
	printf("Hello,world\n");
	return 0;
}

一番最初に提示したプログラム中の#include <stdio.h>は処理系が用意したファイルstdio.hをインクルードするという意味です。上のソースコードは、コンパイラにはこのように見えています。

...//ファイルstdio.hの中身

int main(void){
	printf("Hello,world\n");
	return 0;
}

stdio.hは標準入出力に関する関数のプロトタイプ宣言が含まれています。標準入出力以外にもたくさんの関数が用意されていますが、それらの関数を使う場合はまた別のファイルをインクルードする必要があります。

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main(void){
	printf("Hello,world\n");//stdio.h
	printf("ルート3=%f\n",sqrt(3));//math.h
	printf("文字列リテラルabcdefの長さ=%d\n",strlen("abcdef"));//string.h
	printf("Windowsのコマンドcdを実行します。\n");//stdlib.h
	system("cd");
	return 0;
}

実行結果

Hello,world
ルート3=1.732051
文字列リテラルabcdefの長さ=6
Windowsのコマンドcdを実行します。
C:\Users\gukos\Desktop
(実行結果は環境により異なります)

このサンプルコードでは四つのヘッダファイルをインクルードしそれぞれのファイルの中で定義されている関数を呼び出しました。sqrt()は正の平方根を計算する関数です。strlen()は文字列リテラルの長さを返す関数です。system()はシステムに対し引数をコマンドとしてを実行する関数です。cdはwindowsにおいてカレントディレクトリを表示するコマンドです。筆者はカレントディレクトリがデスクトップなのでデスクトップのパスが表示されました。

#define

#defineは定数マクロまたは関数マクロを定義する関数です。コンパイル前にマクロを指定した文字列に展開します。

#define マクロ名 展開する文字列

変数名と区別するためマクロ名はすべて大文字にする場合が多いです。

#include <stdio.h>
#define YOUSO 3
int main(void){
	int i;
	int num[YOUSO];
	for (i=0;i<YOUSO;i++){
		printf("%d番目の数字を入力してください。",i);
		scanf("%d",&num[i]);
	}
	for (i=0;i<YOUSO;i++){
		printf("%d番目の数字:%d\n",i,num[i]);
	}
	return 0;
}

実行結果

0番目の数字を入力してください。4

1番目の数字を入力してください。5

2番目の数字を入力してください。8

0番目の数字:4
1番目の数字:5
2番目の数字:8

配列の要素数に変数を指定することはできませんが、マクロで指定することはできます。なぜなら、コンパイル前にdefine指令によって定数3に置き換えられるからです。つまり先ほどのプログラムはコンパイラにはこのように見えています。

このソースコードはコンパイラにはこのように見えます。

...//ファイルstdio.hの中身

int main(void){
	int i;
	int num[3];
	for (i=0;i<3;i++){
		printf("%d番目の数字を入力してください。",i);
		scanf("%d",&num[i]);
	}
	for (i=0;i<3;i++){
		printf("%d番目の数字:%d\n",i,num[i]);
	}
	return 0;
}

#define指令にはもう一つ、関数マクロを定義することができます。例えば、

#define MAXOF(a,b) (a>b?a:b)

とマクロ定義すると、関数を定義せずとも関数のような機能を実現できます。

#include <stdio.h>
#define MAXOF(a,b) (a>b?a:b)
int main(void){
	int p,q;
	puts("整数を半角スペース区切りで二つ入力してください:");
	scanf("%d%d",&p,&q);
	printf("pとqの大きいほうは%d\n",MAXOF(p,q));
	return 0;
}

実行結果

整数を半角スペース区切りで二つ入力してください:
-5 6
pとqの大きいほうは6

まとめ

コンパイル前に処理される命令をプリプロセッサ命令といい、#includeと#defineがある。

#includeはヘッダファイルを取り込み、#defineはマクロを定義する命令である。

コメント