名前空間
変種
操作

From cppreference.com
< c‎ | language

(ほとんどの組み込み型の詳細については算術型を、Cライブラリが提供する型関連ユーティリティのリストについては型関連ユーティリティも参照のこと。)

オブジェクト関数、およびは、と呼ばれるプロパティを持ち、オブジェクトに格納された、または式によって評価されたバイナリ値の解釈を決定する。

目次

[編集] 型の分類

Cの型システムは以下の型から構成される。

  • void
  • 基本型
  • char
  • 符号付き整数型
  • 標準: signed char, short, int, long, long long(C99以降)
  • ビット精度: _BitInt(N)。Nは、符号ビットを含む型の表現に使用されるビット数を指定する整数定数式である。Nの各値は異なる型を指定する。
(C23以降)
  • 拡張: 処理系定義、例 __int128
(C99以降)
  • 符号なし整数型
  • 標準: _Bool,(C99以降) unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long(C99以降)
  • ビット精度: unsigned _BitInt(N)Nは、型の表現に使用されるビット数を指定する整数定数式である。Nの各値は異なる型を指定する。このカテゴリには、対応するビット精度の符号付き整数型を持たない型unsigned _BitInt(1)が含まれる。
(C23以降)
  • 拡張: 処理系定義、例 __uint128
(C99以降)
  • 浮動小数点型
  • 実浮動小数点型: float, double, long double
  • 10進実浮動小数点型: _Decimal32, _Decimal64, _Decimal128
(C23以降)
  • 複素数型: float _Complex, double _Complex, long double _Complex
  • 虚数型: float _Imaginary, double _Imaginary, long double _Imaginary
(C99以降)
  • 派生型
(C11 以降)

上記の各型には、constvolatile、およびrestrict修飾子 (修飾子のセマンティクスによって許可される場合) の1つ、2つ、またはすべての3つの組み合わせに対応する、いくつかの限定バージョンが存在する。

[編集] 型のグループ

  • オブジェクト型: 関数型ではないすべての型
  • 文字型: char, signed char, unsigned char
  • 整数型: char, 符号付き整数型, 符号なし整数型, 列挙型
  • 実数型: 整数型および実浮動小数点型
  • 算術型: 整数型および浮動小数点型
  • スカラ型: 算術型、ポインタ型、および nullptr_t(C23以降)
  • 集約型: 配列型および構造体型
  • 派生宣言子型: 配列型、関数型、およびポインタ型

オブジェクト表現のバイト数が型size_t(すなわちsizeof演算子の結果型)で表現できない完全なオブジェクト型を構築すること、実行時にそのようなVLA型を形成することを含め、(C99以降)未定義動作である。

[編集] 互換性のある型

Cプログラムにおいて、異なる翻訳単位で同じオブジェクトまたは関数を参照する宣言は、同じ型を使用する必要はない。それらは十分に類似した型、正式には互換性のある型を使用するだけでよい。これは関数呼び出しや左辺値アクセスにも当てはまる。引数型はパラメータ型と互換性がなければならず、左辺値式の型はアクセスされるオブジェクト型と互換性がなければならない。

TUは、以下のいずれかの場合に互換性がある。

  • それらが同じ型である場合(同じ名前、またはtypedefによって導入されたエイリアス)
  • それらが互換性のある非修飾型の、同一のcvr修飾バージョンである場合
  • それらがポインタ型であり、互換性のある型を指している場合
  • それらが配列型であり、かつ
  • それらの要素型が互換性がある場合、かつ
  • 両方に定数サイズがある場合、そのサイズが同じである。注: 未知の境界の配列は、互換性のある要素型の任意の配列と互換性がある。VLAは、互換性のある要素型の任意の配列と互換性がある。(C99以降)
  • それらが両方とも構造体/共用体/列挙型であり、かつ
  • (C99)一方にタグが宣言されている場合、もう一方も同じタグで宣言されなければならない。
  • 両方が完全な型である場合、そのメンバーは数、互換性のある型での宣言、および名前が完全に一致しなければならない。
  • さらに、それらが列挙型である場合、対応するメンバーも同じ値を持たなければならない。
  • さらに、それらが構造体または共用体である場合、
  • 対応するメンバーは同じ順序で宣言されなければならない(構造体のみ)。
  • 対応するビットフィールドは同じ幅を持たなければならない。
  • 一方が列挙型で、もう一方がその列挙型の基底型である場合
  • それらが関数型であり、かつ
  • その戻り値型が互換性がある場合
  • 両方がパラメータリストを使用する場合、パラメータの数(省略記号の使用を含む)が同じであり、配列からポインタへの型調整および関数からポインタへの型調整を適用し、最上位の修飾子を剥ぎ取った後、対応するパラメータが互換性のある型を持つ場合
  • 一方が旧式の(パラメータなし)定義であり、もう一方がパラメータリストを持つ場合、パラメータリストは省略記号を使用せず、各パラメータはデフォルト引数プロモーションの後、対応する旧式パラメータと互換性がある(関数パラメータ型調整後)。
  • 一方が旧式の(パラメータなし)宣言であり、もう一方がパラメータリストを持つ場合、パラメータリストは省略記号を使用せず、すべてのパラメータ(関数パラメータ型調整後)がデフォルト引数プロモーションの影響を受けない。
(C23まで)

charsigned 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つの型の両方と互換性があり、以下の条件を満たす型である。

  • 両方の型が配列型である場合、以下の規則が適用される。
  • 一方の型が既知の定数サイズの配列である場合、複合型はそのサイズの配列である。
  • そうでない場合、一方の型が評価されない式によってサイズが指定されたVLAである場合、両方の型の複合型を必要とするプログラムは未定義動作となる。
  • そうでない場合、一方の型がサイズが指定されたVLAである場合、複合型はそのサイズのVLAである。
  • そうでない場合、一方の型が未指定サイズのVLAである場合、複合型は未指定サイズのVLAである。
(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

[編集] 関連項目

English 日本語 中文(简体) 中文(繁體)