Typ
(Siehe auch arithmetische Typen für Details zu den meisten integrierten Typen und die Liste der typbezogenen Hilfsmittel, die von der C-Bibliothek bereitgestellt werden.)
Objekte, Funktionen und Ausdrücke haben eine Eigenschaft namens Typ, die die Interpretation des binären Werts bestimmt, der in einem Objekt gespeichert oder von dem Ausdruck ausgewertet wird.
Inhalt |
[bearbeiten] Typklassifizierung
Das C-Typsystem besteht aus den folgenden Typen:
- der Typ void
- Basistypen
- der Typ char
- vorzeichenbehaftete Ganzzahltypen
- Standard: signed char, short, int, long, long long(seit C99)
|
(seit C23) |
|
(seit C99) |
- vorzeichenlose Ganzzahltypen
- Standard: _Bool,(seit C99) unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long(seit C99)
|
(seit C23) |
|
(seit C99) |
- Gleitkommatypen
- reelle Gleitkommatypen: float, double, long double
|
(seit C23) |
|
(seit C99) |
- abgeleitete Typen
| (seit C11) |
Für jeden oben aufgeführten Typ können mehrere qualifizierte Versionen seines Typs existieren, entsprechend den Kombinationen von einem, zwei oder allen drei der Qualifizierer const, volatile und restrict (sofern von der Semantik des Qualifizierers erlaubt).
[bearbeiten] Typengruppen
- Objekttypen: alle Typen, die keine Funktionstypen sind
- Zeichen-Typen: char, signed char, unsigned char
- Ganzzahltypen: char, vorzeichenbehaftete Ganzzahltypen, vorzeichenlose Ganzzahltypen, Aufzählungstypen
- reelle Typen: Ganzzahltypen und reelle Gleitkommatypen
- Arithmetische Typen: Ganzzahltypen und Gleitkommatypen
- Skalartypen: arithmetische Typen, Zeigertypen, und nullptr_t(seit C23)
- Aggregattypen: Arraytypen und Strukturtypen
- Abgeleitete Deklarator-Typen: Arraytypen, Funktionstypen und Zeigertypen
Die Konstruktion eines vollständigen Objekttyps, bei dem die Anzahl der Bytes in seiner Objekt-Repräsentation nicht im Typ size_t darstellbar ist (d.h. dem Ergebnistyp des sizeof-Operators), einschließlich der Laufzeitbildung eines solchen VLA-Typs,(seit C99) ist undefiniertes Verhalten.
[bearbeiten] Kompatible Typen
In einem C-Programm müssen Deklarationen, die sich auf dasselbe Objekt oder dieselbe Funktion in unterschiedlichen Übersetzungseinheiten beziehen, nicht denselben Typ verwenden. Sie müssen nur ausreichend ähnliche Typen verwenden, die formal als kompatible Typen bekannt sind. Dasselbe gilt für Funktionsaufrufe und lvalue-Zugriffe; Argumenttypen müssen kompatibel mit Parametertypen sein und der Typ eines lvalue-Ausdrucks muss kompatibel mit dem Objekttyp sein, auf den zugegriffen wird.
Die Typen T und U sind kompatibel, wenn:
- sie derselbe Typ sind (derselbe Name oder Aliasse, die durch ein
typedefeingeführt wurden) - sie identisch cvr-qualifizierte Versionen von kompatiblen unqualifizierten Typen sind
- sie Zeigertypen sind und auf kompatible Typen zeigen
- sie Arraytypen sind und
- ihre Elementtypen kompatibel sind, und
- falls beide eine konstante Größe haben, diese Größe gleich ist. Hinweis: Arrays unbekannter Größe sind mit jedem Array eines kompatiblen Elementtyps kompatibel. VLA ist mit jedem Array eines kompatiblen Elementtyps kompatibel.(seit C99)
- beide Struktur-/Union-/Aufzählungstypen sind, und
- (C99)Wenn einer mit einem Tag deklariert ist, muss der andere ebenfalls mit demselben Tag deklariert sein.
- wenn beide vollständige Typen sind, müssen ihre Mitglieder in Anzahl genau übereinstimmen, mit kompatiblen Typen deklariert sein und übereinstimmende Namen haben.
- Zusätzlich, wenn es sich um Aufzählungen handelt, müssen entsprechende Mitglieder auch dieselben Werte haben.
- Zusätzlich, wenn es sich um Strukturen oder Unions handelt,
- Entsprechende Mitglieder müssen in der gleichen Reihenfolge deklariert sein (nur Strukturen).
- Entsprechende Bitfelder müssen dieselbe Breite haben.
- einer ein Aufzählungstyp ist und der andere der zugrundeliegende Typ dieser Aufzählung ist
- sie Funktionstypen sind und
- ihre Rückgabetypen kompatibel sind
- sie beide Parameterlisten verwenden, die Anzahl der Parameter (einschließlich der Verwendung von Auslassungspunkten) gleich ist und die entsprechenden Parameter, nachdem Array-zu-Zeiger- und Funktions-zu-Zeiger-Typanpassungen angewendet wurden und nach Entfernung von Top-Level-Qualifizierern, kompatible Typen haben
|
(bis C23) |
Der Typ char ist nicht kompatibel mit signed char und nicht kompatibel mit unsigned char.
Wenn zwei Deklarationen dasselbe Objekt oder dieselbe Funktion bezeichnen und keine kompatiblen Typen verwenden, ist das Verhalten des Programms undefiniert.
// 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
Hinweis: C++ hat kein Konzept von kompatiblen Typen. Ein C-Programm, das zwei Typen in verschiedenen Übersetzungseinheiten deklariert, die kompatibel, aber nicht identisch sind, ist kein gültiges C++-Programm.
[bearbeiten] Zusammengesetzte Typen
Ein zusammengesetzter Typ kann aus zwei Typen gebildet werden, die kompatibel sind; er ist ein Typ, der mit beiden der beiden Typen kompatibel ist und die folgenden Bedingungen erfüllt:
- Wenn beide Typen Arraytypen sind, werden die folgenden Regeln angewendet:
- Wenn ein Typ ein Array mit bekannter konstanter Größe ist, ist der zusammengesetzte Typ ein Array dieser Größe.
|
(seit C99) |
- Andernfalls sind beide Typen Arrays unbekannter Größe und der zusammengesetzte Typ ist ein Array unbekannter Größe.
- Der Elementtyp des zusammengesetzten Typs ist der zusammengesetzte Typ der beiden Elementtypen.
|
(bis C23) |
- Wenn beide Typen Funktionstypen mit Parameter-Typ-Listen sind, ist der Typ jedes Parameters in der zusammengesetzten Parameter-Typ-Liste der zusammengesetzte Typ der entsprechenden Parameter.
Diese Regeln gelten rekursiv für die Typen, von denen die beiden Typen abgeleitet sind.
// 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]);
Für einen Bezeichner mit interner oder externer Bindung, der in einem Geltungsbereich deklariert wird, in dem eine vorherige Deklaration dieses Bezeichners sichtbar ist, wird, wenn die vorherige Deklaration eine interne oder externe Bindung angibt, der Typ des Bezeichners bei der späteren Deklaration zum zusammengesetzten Typ.
[bearbeiten] Unvollständige Typen
Ein unvollständiger Typ ist ein Objekttyp, dem ausreichende Informationen fehlen, um die Größe von Objekten dieses Typs zu bestimmen. Ein unvollständiger Typ kann zu einem bestimmten Zeitpunkt in der Übersetzungseinheit vervollständigt werden.
Die folgenden Typen sind unvollständig:
- der Typ void. Dieser Typ kann nicht vervollständigt werden.
- Arraytyp unbekannter Größe. Er kann durch eine spätere Deklaration, die die Größe angibt, vervollständigt werden.
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)
- Struktur- oder Union-Typ unbekannten Inhalts. Er kann durch eine Deklaration derselben Struktur oder Union, die seinen Inhalt später im selben Geltungsbereich definiert, vervollständigt werden.
struct node { struct node* next; // struct node is incomplete at this point }; // struct node is complete at this point
[bearbeiten] Typennamen
Ein Typ muss möglicherweise in anderen Kontexten als der Deklaration benannt werden. In diesen Situationen wird ein Typname verwendet, der grammatisch exakt gleich ist wie eine Liste von Typ-Spezifizierern und Typ-Qualifizierern, gefolgt von dem Deklarator (siehe Deklarationen), wie er zur Deklaration eines einzelnen Objekts oder einer Funktion dieses Typs verwendet würde, nur dass der Bezeichner weggelassen wird.
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
Abgesehen davon sind überflüssige Klammern um den Bezeichner in einem Typnamen bedeutungsvoll und stellen "Funktion ohne Parameterangabe" dar.
int (n); // declares n of type int sizeof(int ()); // uses type "function returning int"
Typennamen werden in den folgenden Situationen verwendet:
| (seit C99) | |
| (seit C11) |
Ein Typname kann einen neuen Typ einführen.
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
[bearbeiten] Referenzen
- C23-Standard (ISO/IEC 9899:2024)
- 6.2.5 Typen (S. TBD)
- 6.2.6 Repräsentationen von Typen (S. TBD)
- 6.2.7 Kompatibler Typ und zusammengesetzter Typ (S. TBD)
- C17-Standard (ISO/IEC 9899:2018)
- 6.2.5 Typen (S. 31-33)
- 6.2.6 Repräsentationen von Typen (S. 31-35)
- 6.2.7 Kompatibler Typ und zusammengesetzter Typ (S. 35-36)
- C11-Standard (ISO/IEC 9899:2011)
- 6.2.5 Typen (S. 39-43)
- 6.2.6 Repräsentationen von Typen (S. 44-46)
- 6.2.7 Kompatibler Typ und zusammengesetzter Typ (S. 47-48)
- C99-Standard (ISO/IEC 9899:1999)
- 6.2.5 Typen (S. 33-37)
- 6.2.6 Repräsentationen von Typen (S. 37-40)
- 6.2.7 Kompatibler Typ und zusammengesetzter Typ (S. 40-41)
- C89/C90-Standard (ISO/IEC 9899:1990)
- 3.1.2.5 Typen
- 3.1.2.6 Kompatibler Typ und zusammengesetzter Typ
[bearbeiten] Siehe auch
| C++ Dokumentation für Typ
|