前処理(プリプロセス)
前処理指令とは、「#」前処理字句で始まり、それに続く最初の改行文字で終わる一連の前処理字句です。
前処理指令によって、 ソースファイルの一部分を条件によって処理したり読み飛ばしたり、
他のソースファイルを組み込んだり、 マクロを置き換えたりすることができます。
これらの処理は、概念的にはその翻訳単位の翻訳の前に行うので、前処理と呼びます。
翻訳フェーズ
C言語のコンパイルは、大きく分けて、「前処理(プリプロセス)」、「(狭義の)コンパイル」、
そして「リンク」の順に解決されます。
このような順序は、JIS X3010:2003 の中の「5.1.1.2 翻訳フェーズ」で規定されています。
翻訳フェーズの大まかな流れは以下のようになります。
ソースファイル中の物理的な文字を内部表現に置換する。改行コードや文字コードの置換もここで行われる。
処理系定義の多バイト文字 → 対応するソース文字集合
3 文字表記(trigraph sequence) → 対応する文字
※ gcc はデフォルトでは trigraph 禁止になっています
2. 接合(逆斜線文字処理)
行末に逆斜線文字 \ があれば、物理ソース行を連結し、論理ソース行を生成する。
3. 前処理字句・空白類文字整理
ソースファイルを前処理字句と空白類(注釈を含む)の並びに分解する。
注釈はひとつの空白文字に置換する。
4. 前処理
前処理指令(プリプロセッサ・ディレクティブ)を実行する。
マクロ呼出しを展開する。
_Pragma 式を実行する。
#include 指令を展開し、取り込んだソースファイルに対して、1.~4.を再帰的に実行する。
すべての前処理指令を削除する。
5. 文字定数および文字列定数中の各要素を、対応する実行文字集合に置換する。
6. 連結(文字列リテラル)
隣接する文字列リテラルを連結する。
7. 翻訳
翻訳単位として翻訳する。
前処理字句 → 字句に変換する。
字句の構文および意味を解析する。
8. 連係(オブジェクト、関数)
すべての外部オブジェクトおよび外部関数の参照を解決する。
その翻訳単位中に定義されていない関数およびオブジェクトへの外部参照を解決するため、 ライブラリの構成要素に連係する。
これらすべての翻訳出力をまとめて、実行環境上で実行に必要な情報を含む一つのプログラムイメージを作る。
ここで、1.~6.がいわゆる「前処理」、7.が「(狭義の)コンパイル」、そして8.がリンクに相当します。
#include文の利用
#indlude前処理指令は、 h文字列ではヘッダを、q文字列ではソースファイルをそれぞれ取り込みます。
「#include "q文字列"」の探索をサポートしていない場合や、探索が失敗した場合は、 同じ文字列を「#include <h文字列>」と読み替えたのと同じ規則で再処理します。
#include文 構文
#include <h文字列> または #include "q文字列"
<>で指定時
<>(角括弧)は、windows標準のヘッダファイルをインクルードする際に使用します。
ファイル名が角括弧でくくられている場合は、コンパイラ内に指定されているシステム内の標準の場所(通常は \usr\include ディレクトリ)を優先的に検索します。
""で指定時
""(ダブルクォーテーション)は、自分たちで作っているユーザヘッダファイルをインクルードする際に使用します。
ファイル名がダブルクォーテーションでくくられている場合は、カレントディレクトリ(ソースが置かれているディレクトリ・コンパイルを行うディレクトリ)を優先的に検索します。
#include文を使用した記述例
// #include文 program in C.
#include <stdio.h>
#include <string.h>
int main(int argc, char *args[])
{
char comment[12]; // コメント
int rank = 2; // ループカウンタ
// string.h内に定義されているstrncpyを使用します。
strncpy(comment, "Graet!!", sizeof(comment));
printf("Rank > %d %s\n", rank, comment);
return 0;
}
標準ヘッダ
標準ヘッダとは、C言語の標準規格で定められている標準ライブラリの関数宣言が行われているヘッダ群のことです。
型の宣言やマクロの定義も行われています。JIS X3010:2003(ISO/IEC 9899:1999)、通称C99では、標準ヘッダとして以下の24ファイルを定めています。
標準ヘッダ一覧
ヘッダ | 名称 | 概要 |
---|---|---|
assert.h | 診断機能 | 実行時診断を行うassertマクロを定義 |
complex.h | 複素数計算 | 複素数計算をサポートするマクロ、関数を宣言、定義(C99追加) |
ctype.h | 文字操作 | 文字分類、文字変換に有用な関数を宣言 |
errno.h | エラー | ライブラリ関数内エラーの報告用マクロを定義 |
fenv.h | 浮動小数点環境 | 浮動小数点環境へのアクセス手段を提供するための型、マクロ、関数を宣言、定義(C99追加) |
float.h | 浮動小数点型の特性 | 浮動小数点型の大きさや特性を表すマクロを定義 |
inttypes.h | 整数型の書式変換 | 最大幅の整数を操作する関数、及び数値文字列を最大幅の整数に変換する関数を宣言(C99追加) |
iso646.h | 代替つづり | 演算子の代替つづりマクロを定義(C95追加) |
limits.h | 整数型の大きさ | 整数型の大きさを表すマクロを定義 |
locale.h | 文化圏固有操作 | 文化圏固有のデータ等の操作を行う型、マクロ、関数を宣言、定義 |
math.h | 数学 | 数学的な演算を行う関数、及び関連するマクロを宣言、定義 |
setjmp.h | 非局所分岐 | 関数の枠組みを越えた分岐を制御するための型、マクロ、関数を宣言、定義 |
signal.h | シグナル操作 | 種々のシグナルを操作するための型、マクロ、関数を宣言、定義 |
stdarg.h | 可変個数の実引数 | 可変個の実引数を実現するための型、マクロを定義 |
stdbool.h | 論理型及び論理値 | 論理型及び論理値に関連するマクロを定義(C99追加) |
stddef.h | 共通の定義 | 処理系に依存する型、マクロを定義 |
stdint.h | 整数型 |
指定幅を持つ整数型を宣言 また、それらの宣言に対応するマクロを定義(C99追加) |
stdio.h | 入出力 | 入出力に関連する型、マクロ、関数を宣言、定義 |
stdlib.h | 一般ユーティリティ | 一般ユーティリティに関連する型、マクロ、関数を宣言、定義 |
string.h | 文字列操作 | 文字列の操作を行うための型、マクロ、関数を宣言、定義 |
tgmath.h | 型総称数学関数 | 数学関数の型総称マクロを定義 |
time.h | 日付及び時間 | 時間を扱うための型、マクロ、関数を宣言、定義 |
wchar.h |
多バイト文字 及びワイド文字拡張ユーティリティ |
多バイト文字、ワイド文字に関連する型、マクロ、関数を宣言、定義(C95追加) |
wctype.h |
ワイド文字種分類 及びワイド文字大文字小文字変換ユーティリティ |
ワイド文字種の分類や大文字小文字変換に有用な型、マクロ、関数を宣言、定義(C95追加) |