C++ 移行ガイド

C ライブラリヘッダー

互換モードでは、これまでとまったく同じ方法で C 標準のヘッダーを使用できます。標準ヘッダーは、 使用中のリリースの Solaris に含まれる /usr/include ディレクトリにあります。

ここで説明する C ライブラリヘッダーとは、ISO C 標準 (1990 年の ISO 9899) と、それ以降の追補 (1994 年) で定義されている以下の 17 のヘッダーです。


<assert.h> <ctype.h>  <errno.h>  <float.h>  <iso646.h> <limits.h>
<locale.h> <math.h>   <setjmp.h> <signal.h> <stdarg.h> <stdio.h>
<stdlib.h> <string.h> <time.h>   <wchar.h>  <wctype.h>

/usr/include ディレクトリとその下位ディレクトリに存在する、その他の数百のヘッダーは、C 言語標準に規定されていないため、この言語の変更による影響を受けることはありません。

C++ 標準では、C 標準のヘッダーの定義が変更されています。

これらのヘッダーは、旧リリースの Sun C++ と同様の方法で C++ プログラムにインクルードして使用することができますが、以下のことに注意してください。

C++ 標準では、型、オブジェクト、これらのヘッダー中で使用する関数名は、大域的な名前空間だけでなく、std 名前空間にも記述するよう規定しています。つまり、Solaris (Solaris 7 も含む) に付属しているヘッダーはそのままでは使用できないということです。標準モードでコンパイルする場合は、C++ 5.0 コンパイラに付属しているヘッダーを使用してください。ヘッダーが正しくないと、プログラムのコンパイルやリンクが失敗する可能性があります。

唯一の制限として、ヘッダーにはパス名ではなく標準のヘッダー名を使用してください。次の文は正しい例です。


#include <stdio.h> // 正しい

次の文は正しくない例です。


#include“/usr/include/stdio.h”    // 誤り
#include </usr/include/stdio.h> // 誤り

C++ 標準では、17 個ある C 標準のヘッダーのすべてに、別のバージョンのヘッダーが追加されています。つまり、<NAME.h> 形式のすべてのヘッダーについて、ヘッダー名の最後の .h を落とし、先頭に c を追加した <cNAME> という形式の名前を持つヘッダーがあります (NAME は名前を示します)。例:<cstdio><cstring><cctype>

新しいバージョンのヘッダーには、従来の形式のヘッダーで使用されていた名前が含まれていますが、新しいバージョンのヘッダーは std 名前空間にのみ存在します。次に、C++ 標準に則った使用例を示します。


#include <cstdio>
int main() { 		
    printf(“Hello,”);            // エラー、printf が不明
    std::printf(“world!¥n”);     // OK
}

<stdio.h> の代わりに <cstdio> が使用されているため、printf という名前は、名前空間 std にあるだけで、大域的な名前空間にはありません。printf の名前を修飾するか、using 宣言を追加する必要があります。


#include <cstdio>
using std::printf;
int main() {
    printf(“Hello,”);            // OK
    std::printf(“world!¥n”);     // OK
}

/usr/include 中の C 標準のヘッダーには、C 標準では使用が許可されていない宣言が多数含まれています。これらの宣言が存在しているのは、慣習上の理由によります。つまり、UNIX システムにおいては、これらのヘッダー中で慣例的に標準外の宣言が使用されてきたということ、また、他の標準 (POSIX や XOPEN など) においては、そうした宣言が必要になるためです。互換性を維持するため、Sun C++ の <NAME.h> ヘッダーには、そうした名前が残されていますが、これらの名前は、大域的な名前空間にしか存在せず、新しいバージョンの <cNAME> ヘッダーには存在しません。これは、新しいヘッダーが以前のプログラムには使用されていないため、互換性や慣習上の問題が生じることはないためです。<cNAME> は、一般的なプログラミングに役立たないと思われるかもしれませんが、最大の移植性を持つ標準的な C++ コードを作成するには、<cNAME> ヘッダーに移植不可能な宣言が含まれないようにする必要があります。<stdio.h> を使用した例を次に示します。


#include <stdio.h>                  // 大域的な名前空間の stdin
int f() { return fileno(stdin); }       // OK
int g() { return std::fileno(stdin); }  // エラー

次の例では、<cstiod> を使用しています。


#include <cstdio>                        //名前空間 std の stdin
int f() { return fileno(std::stdin); }       //エラー
int g() { return std::fileno(std::stdin); }  //エラー

上記の例の中の fileno は、互換性を維持するために <stdio.h> に残されている「標準外」の関数です。この関数は、大域的な名前空間にのみ存在し、std 名前空間には存在しません。標準外の関数であるため、<cstdio> にも存在しません。


注 -

Solaris 2.5.1 および 2.6 では、C++ 5.0 の C 標準のヘッダーは、必ずしもすべての点で C++ 標準に準拠しているわけではありません。


C++ 標準では、同じコンパイル単位で <NAME.h><cNAME> の両方のバージョンの C 標準ヘッダーを使用することを許可しています。一般的に、このことが意図的に行われることはないと思われますが、たとえば、使用するプロジェクトヘッダーに <stdlib.h> が含まれていて、作成したコードに <cstdlib> がインクルードされたときには、このことが起こります。Solaris 2.5.1 と 2.6 環境では、いくつかのヘッダー、特に <wchar.h><cwchar><wctype.h><cwctype> ヘッダーの組み合わせについては機能しません。これらのヘッダーを使用したときにコンパイラのエラーが出力された場合は、<cNAME> 版ではなく、<NAME.h> 版のヘッダーを使用してください。