ソースファイルの分割
この記事では、ソースコードを複数のファイルに分けて作る方法を紹介します。ソースコードが複数ファイルに分割できると、複数人の開発者で共同してプログラムを制作できます。今回は、main関数をファイルmain.cに書き、自作関数getNumをファイルgetnum.cに作ります。
main.c
#include <stdio.h>
#include "getnum.h"
int main(void){
int a,b;
a=getNum("a:整数を入力してください");
b=getNum("a:整数を入力してください");
printf("aとbのうち大きい数字は%d\n",a>b?a:b);
return 0;
}
getnum.h
int getNum(const char *str);
getnum.c
#include <stdio.h>
int getNum(const char *str){
int n;
puts(str);
scanf("%d",&n);
return n;
}
実行結果
a:整数を入力してください
6
a:整数を入力してください
3
aとbのうち大きい数字は6
main関数では関数getNumのプロトタイプ宣言を含むヘッダファイルgetnum.hをインクルードしています。自作のヘッダファイルはダブルコーテーションで囲む必要があります。
このように、ソースファイルを2つ以上作成する場合はそれに対応するヘッダファイルが必要で、main関数ではヘッダファイルのみをインクルードします。
ソースファイルが3つ以上になっても同様で、それぞれのソースファイルに対してヘッダファイルを定義し、main関数を含むソースファイルからはヘッダファイルをインクルードします。
ヘッダファイルの2重インクルードを防ぐ
あるソースファイルA.cのなかで、別のソースファイルB.cの関数を呼び出すことが可能ですが、そのときはA.cの中でB.hをインクルードしないといけません。また、別のソースファイルC.cでA.cで定義される関数とB.cで定義される関数の両方を呼び出したいときは、C.cの中でA.hとB.hをインクルードすることになります。すると、C.cをコンパイルするときにA.hの内部でB.hをインクルードしているためB.hを2重に含むこととなり、エラーが発生してしまいます。
そんなときは、ヘッダファイルの2重インクルードを防ぐ必要があります。これを、インクルードガードといいます。
インクルードガードは、マクロを定義して実装します。#ifndefと#endifを利用すると、マクロが定義されていない場合のみコンパイルすることができます。
#ifndef マクロ名
//マクロ名が定義されているときのみ実行する処理
#endif
さきほどのgetnum.hをインクルードガードに対応させると、このようになります。
#ifndef MYHEADER_GETNUM_INCLUDE
#define MYHEADER_GETNUM_INCLUDE
int getNum(const char *str);
#endif
マクロの名前はMYHEADER_GETNUM_INCLUDEとしました。インクルードガードでしか使わない名前なので分かりにくくても特に問題はありません。マクロ名は長い方が別のプログラムで使用されるマクロとかぶりにくくなるでしょう。1回目にインクルードする時は、マクロ定義されていないので、ヘッダーファイル内がコンパイルされます。その時にマクロ名が定義されます。2回目以降インクルードする時は、既にマクロ名は定義されているのでコンパイルされません。
Visual Studioなどの一部の処理系では#pragma onceと書くと自動で2重インクルードを防ぐことができます。ただし、C言語標準の仕様ではありません。
#pragma once
int getNum(const char *str);
まとめ
ソースファイルを複数個に分割して制作するには、それぞれのソースファイルに対応したヘッダファイルを作成するのが一般的である。
ヘッダファイルには関数のプロトタイプ宣言などが含まれており、main関数を含むソースファイルではヘッダファイルのみをインクルードする。
コメント