ヘッダーファイルとは?
ソースコードやアプリで関数を共通に利用したい「標準ライブラリ」を使いたい場合に使います。
標準ライブラリに用意されている様々な関数について、その名前の引数、戻り値の定義等、関数を呼び出すために必要となる宣言の部分のみ(プロトタイプ宣言)を記述したファイルでもあります。
他には、ソースファイル(c,cpp)と比較して、変数、関数、マクロ等を定義するファイル(.h)でもあります。
ヘッダファイルを事前にソースファイルの先頭に取り込むことで、ヘッダファイルに定義されている外部ファイルの関数を使えるようになります。
C++では?
マクロは使うのか?
C言語では、マクロを使って様々な複雑な処理を行わせたりしますが、C++ではそのようなことはあまり行いません。
C++でのマクロの用途としては、「二重インクルードの防止」や、「ビルド環境の取得」程度になります。
ヘッダファイル内ではusing指令を使うべきではない。
通常、名前空間ではソースファイルのプログラム記述を簡素化するためにusing指令が使われたりします。
しかし、ヘッダファイルではusing指令を使うべきではありません。
ヘッダファイルは、ファイル内容を別ファイルに埋め込むので、慎重に使うべきusing指令の影響範囲が広がってしまいます。
ヘッダファイル自体は、グローバルな存在ですので、自分たちが作ったプログラムの外にまで影響してしまう可能性もあります。
using指令の影響等は下記の記事でも解説しておりますので、ご確認ください。
プリプロセッサとは?
コンパイラが動作する前に、ソースコードに前処理を行うためのソフトウェアです。
ソースコードはまずプリプロセッサで前処理をされてから、コンパイラに引き渡されます。
プリプロセッサの主な作業
- インクルード処理
- マクロ処理
- コンパイル対象の条件分岐
インクルード処理
「#include」とうい命令を探し出して、ソースコードに展開してくれます。
なので、ソースコードは、実際に記述した内容よりもかなり長い内容になります。
インクルードにも下記のように種類があります。
#include <ヘッダファイル名>
コンパイラが定めるインクルード用ディレクトリからファイルを探す。
例えば、「stdio.h」等はコンパイラをインストールしたインクルードディレクトリに配置されるためコチラを指定します。
#include "ヘッダファイル名"
コンパイル中のファイルにあるディレクトリからファイルを探す。
ただし、見つからなければコンパイラが定めるインクルード用ディレクトリからファイルを探します。
例えば、自作したヘッダファイル等は同じ階層に配置するのでこちらを指定します。
マクロ処理
マクロ処理の存在意義
基本的には、定数や関数と同じような役割だが、それらに比べるとCPUやメモリを通常の関数等に比べて節約できるためです。
現代は、十分すぎるほどCPUやメモリが高性能化しているので、積極的には使わない方がよいでしょう。
ただ、過去に作られたソースでは多く使われている技術ではあるので、読むために理解をしましょう。
#define
ソースコード内にある文字列を、別文字列に単純置換する機能を持っており、この置換処理を展開と呼びます。
置換処理が行われた後にコンパイルが行われるので、仮に置換前がプログラムとして不完全でも、置換後に完全であればエラーになりません。
用途としては、ソース内の数値や、文字列リテラルをより読みやすくするためです。
例えば、定数等を定義しておくのに使われており、古くから使われています。マクロ定数とも呼びます。
構文
1 |
#define 置換前文字列 置換後文字列 |
定義済みマクロ定数
下記のマクロ定数は、プログラマが定義しなくても自動で定義されます。デバッグ等で使ったりします。
マクロ定数名 | 説明 |
---|---|
_FINE_ | このマクロが書かれているソースファイル名 |
_LINE_ | このマクロが記述された位置(ソースの行番号) |
_DATE_ | プリプロセッサが起動された日付 |
_TIME_ | プリプロセッサが起動された時刻 |
_func_ | このマクロが書かれている関数名 |
NULL | ヌルポインタを指す。 |
マクロ関数
1 |
#define calc(X,Y) X-Y |
例えば、上記のような定義があった場合は、ソース内で「clac(3,2)」等と呼び出すことができます。そうすると「3-2」に置換されます。
コンパイル対象の条件分岐
現代のマクロのメリットとしては、これが主でしょう。
「#ifdef マクロ定数 ~ #endif」等の宣言によって、実行したいソースコードを分岐させたりすることができます。
主に、下記のようなケースで分岐させたりします。
- コンパイラの種類やバージョンが多くある環境の場合
- 実行環境が多くある場合
- デバッグ時
また、二重インクルードの防止のためにも使われていたりしますね。
プリプロセッサの処理が終わったら
プリプロセッサによる処理が完了したら、次はコンパイラに処理が受け継がれます。
詳しくは、下記の記事で解説をしています。
この記事へのコメントはありません。