第15回
関数の宣言~ライブラリとヘッダファイル

プリ・コンパイルド・ヘッダ

処理系に備わっているヘッダファイルは、まず滅多に書き換えられません。しかしそのサイズは意外に大きく、コンパイル全体の大半がヘッダファイルの処理に費やされている場合もあります。その無駄をなんとかしようと考え出されたのが『プリ・コンパイルド・ヘッダ』です。

ヘッダファイルはでかい!

複数のソースから1つのプログラムを作る過程や、その際に生じる『参照の垣根』の問題などは、回を追って紹介しましょう。ここでは、ライブラリにまとめられている関数を使用するためには関数のextern宣言が必要で、それはヘッダファイルに記述されている──ということを知っておいてください。

ライブラリが役割ごとに分類されており、ヘッダファイルもライブラリ単位で分類されているのはそのためです。

しかし、分類されているとは言え、ヘッダファイルのサイズはバカになりません。LSI-Cの場合、stdio.hは約4KB、stdlib.hは約3KB……と、ソースとしてはそこそこの大きさです。

ヘッダファイルは、ソースの先頭で#includeプリプロセッサ指令によって取り込まれる訳ですが、元のソースのサイズが1KBでもstdio.hを取り込めば、コンパイラが読み込むソースファイル全体のサイズは5KBに膨れ上がってしまいます。

一度コンパイルしてそれで完成──といった奇跡はまず起こりません。本コラムで既に述べたように、完成までにはバグを見つけては修正して再コンパイル……という作業を繰り返すことになります。

そのような場合、元のソースの一部を修正するだけでも、コンパイラは書き換えられていない4KBのヘッダファイルまで読み込むことになります。

ヘッダだけコンパイルしておけばいいじゃないか

よく考えると(よく考えなくても)、これは相当な無駄です。ソースを手直しして再コンパイル──という繰り返しの中で、まったく書き換えられていないヘッダファイルのコンパイルに、元のソースに対してよりも多くの時間を割いているのですから。

と、いうことで、基本的に変更されることのないヘッダファイルを予めコンパイルしておけばいいじゃないか……という発想が生まれました。それが、プリ・コンパイルド・ヘッダ(pre-compiled header)です。

プリ・コンパイルド・ヘッダを使うと、Cのソースとそこに取り込まれているヘッダファイルとが別々にコンパイルされてから結合されます。最初のコンパイルでは、プリ・コンパイルド・ヘッダを使わない場合とほぼ同じ程度の時間がかかります。しかし、ソースの一部を修正して2回目以降のコンパイルを行うと、今度はヘッダファイルをコンパイルしないで済むため、処理時間が大幅に短縮されます。

このようにプリ・コンパイルド・ヘッダは、巨大なヘッダファイルを多数取り込んだたくさんのソースファイルからアプリケーションを作る際の効率化に役立ちます。

Visual C++で使える

Microsoft社のオンラインヘルプやMSDNライブラリでは、プリ・コンパイルド・ヘッダは日本語で「プリコンパイル済みヘッダー」と表記されており、Visual C++で利用できます。

プロジェクトを新規作成するときのウィザード画面で「プリコンパイル済みヘッダー」にチェックを入れて有効にするだけです。C++でWindowsアプリケーションを作る場合は、これが標準で指定されており、チェックは外せません(画面1)。

本コラムで作成しているサンプルのようなコンソールモードのアプリケーションの場合は、チェックボックスのON/OFFが機能するようになり、「プリコンパイル済みヘッダー」を使うかどうかを選択できます(画面2)。

あとがき

hiropの『ちょっと気になる専門用語』~《プリコンパイル済みヘッダー》

本文に書いたように、Microsoft社の日本語ドキュメントではプリ・コンパイルド・ヘッダ(pre-compiled header)を「プリコンパイル済みヘッダー」と表記しています。この表現、どうも気になってしまいます。

"pre"は「あらかじめ~された」という意味の接頭辞ですから「~済み」というニュアンスも含まれます。ですから、「プリコンパイル済み」という日本語は「予めコンパイル済みされた……」という意味に取れてしまい、なんだかしっくりこないのです。

確かに「プリ・コンパイルド・ヘッダ」というカタカナ語は長くて意味が分かりにくいので、もっとすっきりした日本語を使った方がよいとは思います。ならば、「コンパイル済みヘッダ」でいいのではないかと思うのですが、いかがでしょう?

とりあえず本コラムでは、長ったらしいけれど「プリ・コンパイルド・ヘッダ」と表記しておきます。御了承ください。