ナビゲーションリンクをスキップ | |
印刷ビューの終了 | |
Oracle Solaris Studio 12.3: C ユーザーガイド Oracle Solaris Studio 12.3 Information Library (日本語) |
K&R C では (ISO C の場合はさらに顕著ですが)、同じ要素を参照する 2 つの宣言を同じでないものにできます。ISO C は、このような「ある程度似ている」型を示すために、「互換型」という用語を使用します。この節では、この互換型と、2 つの互換型を結合した結果である「複合型」を説明します。
C プログラムが、各オブジェクトまたは関数の宣言を一度だけ許可されているとしたら、互換型は必要ありませんでした。しかし、同じ要素を参照する複数の宣言を許可するリンク、関数のプロトタイプ、および分割コンパイルには、このような機能が必要です。複数の翻訳単位 (ソースファイル) 間では、型の互換性の規則は 1 つの翻訳単位内のものとは異なります。
各コンパイルはおそらく別々のソースファイルを参照するため、分割コンパイル間の互換型に対して、ほとんどの規則は事実上次のように構造化されています。
一致するスカラー (整数、浮動小数点、およびポインタ) 型は、同じソースファイル内にある場合のように、互換性を持たなければならない。
一致する構造体、共用体、および列挙型のメンバー数は同じでなければならない。一致する各メンバーは (分割コンパイルという意味で) 互換型を持たなければならない (ビットフィールド幅も含む)。
一致する構造体のメンバーの順番は、同じでなければならない。共用体と列挙型のメンバーの順番は問題にならない。
一致する列挙型のメンバーの値は、同じでなければならない。
さらに、構造体、共用体、および列挙型のメンバーの名前 (名前なしメンバーに名前がないということ) も一致しなければいけません。しかし、それぞれのタグは必ずしも一致する必要はありません。
同じスコープ内の 2 つの宣言が同じオブジェクトまたは関数を記述するとき、この 2 つの宣言は互換型を指定しなければいけません。これら 2 つの型は次に、最初の 2 つと互換性を持つ、1 つの複合型に結合されます。
互換型は再帰的に定義されます。一番下は型指定子のキーワードです。これらの規則は、unsigned short は unsigned short int と同じであり、型指定子なしの型は int を持つものと同じであることを示します。ほかのすべての型は、派生元の型が互換性を持つときだけ、互換性を持ちます。たとえば、修飾子 const と volatile が同じであり、修飾されていない基底型が互換性を持つ場合、2 つの修飾型は互換性を持ちます。
2 つのポインタ型が互換性を持つためには、この 2 つのポインタが指す型が互換性を持ち、2 つのポインタが同じように修飾されていなければいけません。ポインタの修飾子は * のあとに指定されることを思い出してください。次の 2 つの宣言は、同じ型 int への異なる修飾子を持つ 2 つのポインタを宣言しています。
int *const cpi; int *volatile vpi;
2 つの配列型が互換性を持つためには、この 2 つの配列の要素の型が互換性を持たなければいけません。両方の配列の型のサイズが指定されている場合は、両方のサイズも一致しなければいけません。つまり、不完全な配列型 (「6.11 不完全な型」を参照) は、ほかの不完全な配列型とも、サイズが指定されている配列型とも互換性を持ちます。
関数が互換性を持つためには、次の規則に従います:
2 つの関数型が互換性を持つためには、その戻り型が互換性を持たなければいけません。関数型のいずれかまたはその両方がプロトタイプを持つ場合:規則はより複雑になります。
プロトタイプを持つ 2 つの関数型が互換性を持つためには、(省略記号 (…) も含む) パラメータの数が同じで、対応するパラメータもパラメータ互換でなければいけません。
古い形式の関数定義がプロトタイプを持つ関数型と互換性を持つためには、プロトタイプの最後のパラメータが省略記号 (…) であってはいけません。プロトタイプの各パラメータは、デフォルトの引数拡張の適用後、対応する古い形式のパラメータとパラメータ互換でなければいけません。
古い形式の関数宣言 (定義ではない) が、プロトタイプを持つ関数型と互換性を持つためには、プロトタイプの最後のパラメータが省略記号 (…) であってはいけません。プロトタイプのすべてのパラメータは、デフォルトの引数拡張で影響を受けない型でなければいけません。
2 つの型がパラメータ互換になるためには、これら 2 つの型は、1 番上に修飾子があればそれが削除されたあと、そして、関数型または配列型が適切なポインタ型に変換されたあとに、互換性を持たなければいけません。
signed int は int と同じように動作します。ただし、ビットフィールドは例外の可能性があります。通常の int が unsigned 動作の量を示すことがあります。
列挙型は同じ整数型と互換性を持つ必要があります。移植可能なプログラムの場合、これは、列挙型が別の型であることを意味します。一般的に、ISO C 規格はこのように列挙型を扱います。
2 つの互換型から 1 つの複合型への作成も再帰的に定義されます。不完全な配列型や古い形式の関数型を使用することにより、互換型をお互いに異なるようにできます。同様に、複合型をもっとも簡単に記述するには、元の両方の型 (元の型のすべての使用可能な配列サイズとパラメータリストも含む) と型の互換性を持たせればよいでしょう。