型
(ほとんどの組み込み型の詳細については算術型を、Cライブラリが提供する型関連ユーティリティのリストについては型関連ユーティリティも参照のこと。)
オブジェクト、関数、および式は、型と呼ばれるプロパティを持ち、オブジェクトに格納された、または式によって評価されたバイナリ値の解釈を決定する。
目次 |
[編集] 型の分類
Cの型システムは以下の型から構成される。
- 型 void
- 基本型
- 型 char
- 符号付き整数型
- 標準: signed char, short, int, long, long long(C99以降)
|
(C23以降) |
|
(C99以降) |
- 符号なし整数型
- 標準: _Bool,(C99以降) unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long(C99以降)
|
(C23以降) |
|
(C99以降) |
- 浮動小数点型
- 実浮動小数点型: float, double, long double
|
(C23以降) |
|
(C99以降) |
- 派生型
| (C11 以降) |
上記の各型には、const、volatile、およびrestrict修飾子 (修飾子のセマンティクスによって許可される場合) の1つ、2つ、またはすべての3つの組み合わせに対応する、いくつかの限定バージョンが存在する。
[編集] 型のグループ
- オブジェクト型: 関数型ではないすべての型
- 文字型: char, signed char, unsigned char
- 整数型: char, 符号付き整数型, 符号なし整数型, 列挙型
- 実数型: 整数型および実浮動小数点型
- 算術型: 整数型および浮動小数点型
- スカラ型: 算術型、ポインタ型、および nullptr_t(C23以降)
- 集約型: 配列型および構造体型
- 派生宣言子型: 配列型、関数型、およびポインタ型
オブジェクト表現のバイト数が型size_t(すなわちsizeof演算子の結果型)で表現できない完全なオブジェクト型を構築すること、実行時にそのようなVLA型を形成することを含め、(C99以降)未定義動作である。
[編集] 互換性のある型
Cプログラムにおいて、異なる翻訳単位で同じオブジェクトまたは関数を参照する宣言は、同じ型を使用する必要はない。それらは十分に類似した型、正式には互換性のある型を使用するだけでよい。これは関数呼び出しや左辺値アクセスにも当てはまる。引数型はパラメータ型と互換性がなければならず、左辺値式の型はアクセスされるオブジェクト型と互換性がなければならない。
型TとUは、以下のいずれかの場合に互換性がある。
- それらが同じ型である場合(同じ名前、または
typedefによって導入されたエイリアス) - それらが互換性のある非修飾型の、同一のcvr修飾バージョンである場合
- それらがポインタ型であり、互換性のある型を指している場合
- それらが配列型であり、かつ
- それらの要素型が互換性がある場合、かつ
- 両方に定数サイズがある場合、そのサイズが同じである。注: 未知の境界の配列は、互換性のある要素型の任意の配列と互換性がある。VLAは、互換性のある要素型の任意の配列と互換性がある。(C99以降)
- それらが両方とも構造体/共用体/列挙型であり、かつ
- (C99)一方にタグが宣言されている場合、もう一方も同じタグで宣言されなければならない。
- 両方が完全な型である場合、そのメンバーは数、互換性のある型での宣言、および名前が完全に一致しなければならない。
- さらに、それらが列挙型である場合、対応するメンバーも同じ値を持たなければならない。
- さらに、それらが構造体または共用体である場合、
- 対応するメンバーは同じ順序で宣言されなければならない(構造体のみ)。
- 対応するビットフィールドは同じ幅を持たなければならない。
- 一方が列挙型で、もう一方がその列挙型の基底型である場合
- それらが関数型であり、かつ
- その戻り値型が互換性がある場合
- 両方がパラメータリストを使用する場合、パラメータの数(省略記号の使用を含む)が同じであり、配列からポインタへの型調整および関数からポインタへの型調整を適用し、最上位の修飾子を剥ぎ取った後、対応するパラメータが互換性のある型を持つ場合
|
(C23まで) |
型charはsigned charと互換性がなく、unsigned charとも互換性がない。
2つの宣言が同じオブジェクトまたは関数を参照し、互換性のある型を使用しない場合、プログラムの動作は未定義である。
// Translation Unit 1 struct S { int a; }; extern struct S *x; // compatible with TU2's x, but not with TU3's x // Translation Unit 2 struct S; extern struct S *x; // compatible with both x's // Translation Unit 3 struct S { float a; }; extern struct S *x; // compatible with TU2's x, but not with TU1's x // the behavior is undefined
// Translation Unit 1 #include <stdio.h> struct s { int i; }; // compatible with TU3's s, but not TU2's extern struct s x = {0}; // compatible with TU3's x extern void f(void); // compatible with TU2's f int main() { f(); return x.i; } // Translation Unit 2 struct s { float f; }; // compatible with TU4's s, but not TU1's s extern struct s y = {3.14}; // compatible with TU4's y void f() // compatible with TU1's f { return; } // Translation Unit 3 struct s { int i; }; // compatible with TU1's s, but not TU2's s extern struct s x; // compatible with TU1's x // Translation Unit 4 struct s { float f; }; // compatible with TU2's s, but not TU1's s extern struct s y; // compatible with TU2's y // the behavior is well-defined: only multiple declarations // of objects and functions must have compatible types, not the types themselves
注: C++には互換性のある型という概念はない。異なる翻訳単位で互換性はあるが同一ではない2つの型を宣言するCプログラムは、有効なC++プログラムではない。
[編集] 複合型
複合型は、互換性のある2つの型から構築できる。それは、2つの型の両方と互換性があり、以下の条件を満たす型である。
- 両方の型が配列型である場合、以下の規則が適用される。
- 一方の型が既知の定数サイズの配列である場合、複合型はそのサイズの配列である。
|
(C99以降) |
- そうでない場合、両方の型が未知のサイズの配列であり、複合型は未知のサイズの配列である。
- 複合型の要素型は、2つの要素型の複合型である。
|
(C23まで) |
- 両方の型がパラメータ型リストを持つ関数型である場合、複合パラメータ型リストの各パラメータの型は、対応するパラメータの複合型である。
これらの規則は、2つの型が派生する型に再帰的に適用される。
// Given the following two file scope declarations: int f(int (*)(), double (*)[3]); int f(int (*)(char *), double (*)[]); // C23: Error: conflicting types for 'f' // The resulting composite type for the function is: int f(int (*)(char *), double (*)[3]);
内部または外部のリンケージを持つ識別子が、以前の宣言が見えるスコープで宣言され、以前の宣言が内部または外部リンケージを指定している場合、後の宣言における識別子の型は複合型となる。
[編集] 不完全型
不完全型は、その型のオブジェクトのサイズを決定するのに十分な情報が不足しているオブジェクト型である。不完全型は、翻訳単位のある時点で完了させることができる。
以下の型は不完全である。
- 型void。この型は完了できない。
- 未知のサイズの配列型。サイズを指定する後の宣言によって完了できる。
extern char a[]; // the type of a is incomplete (this typically appears in a header) char a[10]; // the type of a is now complete (this typically appears in a source file)
- 未知の内容の構造体型または共用体型。同じスコープ内で後からその内容を定義する同じ構造体または共用体の宣言によって完了できる。
struct node { struct node* next; // struct node is incomplete at this point }; // struct node is complete at this point
[編集] 型名
型は宣言以外の文脈で名前を付ける必要がある場合がある。これらの状況では、型名が使用される。これは、文法的には、識別子が省略されることを除けば、単一のオブジェクトまたは関数を宣言するのに使用される型指定子と型修飾子のリストの後に宣言子(宣言を参照)が続くものとまったく同じである。
int n; // declaration of an int sizeof(int); // use of type name int *a[3]; // declaration of an array of 3 pointers to int sizeof(int *[3]); // use of type name int (*p)[3]; // declaration of a pointer to array of 3 int sizeof(int (*)[3]); // use of type name int (*a)[*] // declaration of pointer to VLA (in a function parameter) sizeof(int (*)[*]) // use of type name (in a function parameter) int *f(void); // declaration of function sizeof(int *(void)); // use of type name int (*p)(void); // declaration of pointer to function sizeof(int (*)(void)); // use of type name int (*const a[])(unsigned int, ...) = {0}; // array of pointers to functions sizeof(int (*const [])(unsigned int, ...)); // use of type name
識別子を囲む冗長な括弧は、型名では意味を持ち、「パラメータ指定のない関数」を表す。
int (n); // declares n of type int sizeof(int ()); // uses type "function returning int"
型名は以下の状況で使用される。
| (C99以降) | |
| (C11 以降) |
型名は新しい型を導入する場合がある。
void* p = (void*)(struct X { int i; } *)0; // type name "struct X {int i;}*" used in the cast expression // introduces the new type "struct X" struct X x = {1}; // struct X is now in scope
[編集] 参照
- C23標準 (ISO/IEC 9899:2024)
- 6.2.5 Types (p: TBD)
- 6.2.6 Representations of types (p: TBD)
- 6.2.7 Compatible type and composite type (p: TBD)
- C17標準 (ISO/IEC 9899:2018)
- 6.2.5 Types (p: 31-33)
- 6.2.6 Representations of types (p: 31-35)
- 6.2.7 Compatible type and composite type (p: 35-36)
- C11標準 (ISO/IEC 9899:2011)
- 6.2.5 Types (p: 39-43)
- 6.2.6 Representations of types (p: 44-46)
- 6.2.7 Compatible type and composite type (p: 47-48)
- C99標準 (ISO/IEC 9899:1999)
- 6.2.5 Types (p: 33-37)
- 6.2.6 Representations of types (p: 37-40)
- 6.2.7 Compatible type and composite type (p: 40-41)
- C89/C90標準 (ISO/IEC 9899:1990)
- 3.1.2.5 Types
- 3.1.2.6 Compatible type and composite type