C には、<stdio.h>、<string.h>、<stdlib.h> などの 17 個の標準ヘッダーがあります。これらのヘッダーは Solaris オペレーティングシステムに標準で付属しており、/user/include に置かれています。C++ にも同様のヘッダーがありますが、さまざまな宣言の名前が大域の名前空間と std 名前空間の両方に存在するという条件が付加されています。Version 8 より前のリリースの Solaris オペレーティングシステムの C++ コンパイラでは、/usr/include ディレクトリにあるヘッダーはそのまま残して、独自のバージョンのヘッダーを別に用意しています。
また、C++ には、C 標準ヘッダー (<cstdio> 、<cstring>、<cstdlib> など) のそれぞれについても専用のバージョンがあります。C++ 版の C 標準ヘッダーでは、宣言名は std 名前空間にのみ存在します。C++ には、32 個の独自の標準ヘッダー (<string>、<utility>、<iostream> など) も追加されています。
標準ヘッダーの実装で、C++ ソースコード内の名前がインクルードするテキストファイル名として使用されているとしましょう。たとえば、標準ヘッダーの <string> (または <string.h>) が、あるディレクトリにある string (または string.h) というファイルを参照するものとします。この実装には、次の欠点があります。
ヘッダーファイルにファイル名接尾辞 (拡張子) がない場合に、ヘッダーファイルのみを検索すること、またはヘッダーファイルに関する規則を示す makefile を作成することができない。
string というディレクトリまたは実行可能プログラムがあると、そのディレクトリまたはプログラムが標準ヘッダーファイルの代わりに検出される可能性がある。
Solaris 8 オペレーティングシステムより前のリリースの Solaris オペレーティングシステムでは .KEEP_STATE が有効なときのメイクファイルのデフォルトの相互依存関係により、標準ヘッダーが実行可能プログラムに置き換えられる可能性がある (デフォルトの場合、接尾辞がないファイルは構築対象プログラムとみなされる)。
こうした問題を解決するため、コンパイラの include ディレクトリには、ヘッダーと同じ名前を持つファイルと、 一意の接尾辞 .SUNWCCh を持つ、そのファイルへのシンボリックリンクが含まれています。 SUNW はコンパイラに関係するあらゆるパッケージに対する接頭辞、CC は C++ コンパイラの意味、.h はヘッダーファイルの通常の接尾辞です。つまり <string> と指定された場合、コンパイラは <string.SUNWCCh> と書き換え、その名前を検索します。接尾辞付きの名前は、コンパイラ専用の include ディレクトリにだけ存在します。このようにして見つけられたファイルがシンボリックリンクの場合 (通常はそうである)、コンパイラは、エラーメッセージやデバッガの参照でそのリンクを 1 回だけ間接参照し、その参照結果 (この場合は string) をファイル名として使用します。ファイルの依存関係情報を送るときは、接尾辞付きの名前の方が使用されます。
この名前の書き換えは、2 つのバージョンがある 17 個の標準 C ヘッダーと 32 個の標準 C++ ヘッダーのいずれかを、パスを指定せずに山括弧 < > で囲んで指定した場合にだけ行われます。山括弧の代わりに引用符が使用されるか、パスが指定されるか、ほかのヘッダーが指定された場合、名前の書き換えは行われません。
次の表は、よくある書き換え例をまとめています。
表 12–3 ヘッダー検索の例
ソースコード |
コンパイラによる検索 |
注釈 |
---|---|---|
<string> |
string.SUNWCCh |
C++ の文字列テンプレート |
<cstring> |
cstring.SUNWCCh |
C の string.h の C++ 版 |
<string.h> |
string.h.SUNWCCh |
C の string.h |
<fcntl.h> |
fcntl.h |
標準 C および C++ ヘッダー以外 |
"string" |
string |
山括弧ではなく、二重引用符 |
<../string> |
../string |
パス指定がある場合 |
コンパイラが header.SUNWCCh (header はヘッダー名) を見つけられない、コンパイラは、#include 指令で指定された名前で検索し直します。たとえば、#include <string> という指令を指定した場合、コンパイラは string.SUNWCCh という名前のファイルを見つけようとします。この検索が失敗した場合、コンパイラは string という名前のファイルを探します。
「12.7.5 標準ヘッダーの実装」で説明している検索アルゴリズムのため、「12.7.3 代替ライブラリのインストール」で説明している SUNWCCh バージョンの代替 ヘッダーを指定する必要はありません。しかし、これまでに説明したいくつかの問題が発生する可能性もあります。その場合、推奨される解決方法は、接尾辞が付いていないヘッダーごとに、接尾辞 .SUNWCCh を持つファイルに対してシンボリックリンクを作成することです。つまり、ファイルが utility の場合、次のコマンドを実行します。
example% ln -s utility utility.SUNWCCh |
utility.SUNWCCh というファイルを探すとき、コンパイラは 1 回目の検索でこのファイルを見つけます。そのため、utility という名前のほかのファイルやディレクトリを誤って検出してしまうことはありません。
標準 C ヘッダーの置き換えはサポートされていません。それでもなお、独自のバージョンの標準ヘッダーを使用したい場合、推奨される手順は次のとおりです。
すべての代替ヘッダーを 1 つのディレクトリに置きます。
そのディレクトリ内にある代替ヘッダーごとに header.SUNWCCh (header はヘッダー名) へのシンボリックリンクを作成します。
コンパイラを呼び出すごとに -I 指令を指定して、代替ヘッダーが置かれているディレクトリが検索されるようにします。
たとえば、<stdio.h> と <cstdio> の代替ヘッダーがあるとします。stdio.h と cstdio をディレクトリ /myproject/myhdr に置きます。このディレクトリ内で、次のコマンドを実行します。
example% ln -s stdio.h stdio.h.SUNWCCh example% ln -s cstdio cstdio.SUNWCCh |
コンパイルのたびに、オプション -I/myproject/mydir を使用します。
C ヘッダーを置き換える場合は、対になっているもう一方のヘッダーを置き換える必要があります。たとえば、<time.h> を置き換えるときは、<ctime> も置き換える必要があります。
代替ヘッダーは、置き換える前のヘッダーと同じ効果を持っている必要があります。これは、さまざまな実行時ライブラリ (libCrun、libC、libCstd、libc、および librwtool) が標準ヘッダーの定義を使用して構築されているためです。同じ効果を持っていない場合、作成したプログラムはほとんどの場合、正しく動作しません。