C言語のコンパイラは、C言語プログラムをコンパイルするときに、コンパイル前処理を行います。
このコンパイル前処理を行う機能を、プリプロセッサと言い、このプリプロセッサに指示することを、プリプロセッサコマンドと言います。
プリプロセッサコマンドの主な処理には、
・ファイルの挿入(指定したファイルをソースコード内に読み込む)
・ 文字列の置き換え(ソースコード内の文字列を他の文字列に置換する)
があります。
具体的なコマンドを挙げますと、

		#include ・・・ ファイル挿入
		#define ・・・ 文字列置き換え

です。
この#includeや#defineの二つは、C言語でプログラミングをする上で欠かせないものの一つです。
そこで今回のC言語超入門では、コンパイル前処理として重要な#includeや#defineについて解説をしていきます。

ファイル挿入(#include)

コンパイラは、ソースコード内に#includeを見つけますと、#includeで指定しているファイルを読み込み、#includeを記述している場所に挿入します。
そして、ファイルを挿入した後のソースコードに対して、コンパイル処理を実施します。

ファイル挿入(#include)の使い方

まず、#includeでファイルを指定する方法は、以下の2通りがあります。
・ #include <ファイル名>
・ #include “ファイル名”
ファイル名を < > でくくると、開発環境で設定しているフォルダ(ディレクトリ)から、ファイルを読み込みます。
一方で、” ” でファイル名をくくった場合は、カレントフォルダ(現在のフォルダ)からファイルを読み込み、
もし該当するファイルが無い場合は、開発環境で設定しているフォルダから読み込みます。
両者の使い分けに特段の制限はありませんが、開発環境がはじめから用意しているファイルに対しては < > を使い、
プログラマーが自作したファイルに対しては ” ” を使うのが一般的です。
また、読み込むファイル名についても、拡張子を.hにすることが一般的です。

ファイル挿入(#include)のサンプルプログラム

では、#includeを使ったプログラムを見ながら、#includeの動きを確認していきましょう。

/* プログラム1 */
#include <stdio.h>
#include "test.h"
main() {
    printf("x=%d", test());
}
/* ファイル名 : test.h   */
int test(){
    return 10;
}
※プログラム1の実行結果
x=10

プログラム1の冒頭で、#include と、#include “test.h を記述しています。
ここで、開発環境が用意しているstdio.hというファイルと、自作をしたtest.hというファイルを読み込んでいます。
そのため、実際にコンパイラがプログラム1をコンパイルするとき、プログラム1は以下のように変換されます。
(※開発環境によって内容が異なります。)

/* プログラム1 */
#if __SC__ || __RCC__
#pragma once
#endif
#ifndef __STDIO_H
#define __STDIO_H 1
(中略)
/* ファイル名 : test.h   */
int test(){
     return 10;
}
main() {
    printf("x=%d", test());
}

文字列置き換え(#define)

コンパイラは、ソースコード内に#defeinを見つけますと、#defineで指定した文字列を置き換えます。
そして、文字列を置き換えた後のソースコードに対して、コンパイル処理を実施します。

文字列置き換え(#define)の使い方

#defineの記述方法は以下のとおりです。

	#define 文字列1 文字列2

コンパイラは、ソースコード内で「文字列1」を見つけますと、「文字列2」に置き換えて、コンパイル処理を行います。
例えば以下のようにプログラミングしたとしましょう。

	#define   TRUE   1
   		  :
    	  :
	if (x == TRUE) {
    	  :

上記のif文は、コンパイル前処理によって、

	if (x == 1) {

と解釈して処理されます。

文字列の置き換えをする意味

ところで、なぜC言語には、文字列の置き換え処理を行う機能があるのでしょうか。
理由の一つとしては、プログラマー(つまり人間にとって)、プログラムが読みやすくなることが挙げられます。
例えば以下のように、変数xに対して1.08を乗じている処理があったとします。

  x = x *  1.08;

このとき1.08を、以下のように#defineで定義した上で、プログラミングしたとします。

#define   TAX_RATE  1.08
        :
        :
 x = x * TAX_TATE;
        :

#defineを使うことによって、変数xに税率を乗じていることが、すぐに理解できませんか?
また、もう一つのC言語に持ち列の置き換え処理が用意されている理由としては、
文字列の置き換え処理を使うことで、プログラムの修正が楽になることが挙げられます。
例えば上記の例で言いますと、税率が1.08から1.10に変更になったとしたら、

	#define  TAX_RATE  1.10

と記述するだけで、プログラム修正を済ませることが可能になります。
もし、文字列置き換え処理を使わずに、ソースコード上に1.08と書き込んでいたとしたら、たいへんなことになってしまいます。
プログラムをすべてチェックして、1.08を1.10に修正していかなければなりません。
規模の大きなプログラムになりますと、無数の場所を修正することになります。
こんなことをしていたら、プログラムの修正漏れや修正ミスが起きてしまいかねません。
文字列の置き換え処理を利用することは、プログラムが読みやすくなり、修正もしやすくなる、というメリットがあるのです。

C言語超入門の第37回まとめ

さて今回のC言語超入門では、コンパイル前処理について解説してきましたが、いかがでしたでしょうか。
最後にもう一度、ポイントを整理しておきます。
・ コンパイル前処理を行う機能をプリプロセッサと言い、
このプリプロセッサに指示することを、プリプロセッサコマンドと言う
・ #includeは、指定したファイルを記述した箇所に読み込む
・ #defineは、ソースコード内の文字列置き換えを行う
ステップ・バイ・ステップ。焦らず一歩ずつ進んでいきましょう。