©
This document usesPHP Chinese website manualRelease
(有关大多数内置类型的细节以及由C库提供的与类型相关的实用程序的列表,另请参阅算术类型)。
对象,函数和表达式都有一个名为type的属性,它决定了存储在对象中或由表达式求值的二进制值的解释。
C型系统由以下类型组成:
方式void
基本类型
方式char
有符号整数类型
标准:signed char
,short
,int
,long
,long long
(因为C99)
扩展:定义的实现,例如__int128
无符号整数类型
标准:_Bool
(自C99), , ,unsigned char
,,unsigned short
( 因为C99)unsigned intunsigned longunsigned long long
扩展:实现定义,例如__uint128
浮动类型
真正的浮点类型:float
,double
,long double
复杂类型:float _Complex
,double _Complex
,long double _Complex
虚类型:float _Imaginary
,double _Imaginary
,long double _Imaginary
枚举类型
派生类型
数组类型
结构类型
工会类型
函数类型
指针类型
原子类型
对于上面列出的每种类型,可能存在几种其类型的合格版本,对应于const,volatile和restrict限定符(限定符语义所允许的)中的一个,两个或全部三个的组合。
对象类型:不是函数类型的所有类型
字符类型:char
,signed char
,unsigned char
整数类型:char
,有符号整数类型,无符号整数类型,枚举类型
实际类型:整数类型和实际浮动类型
算术类型:整数类型和浮点类型
标量类型:算术类型和指针类型
聚合类型:数组类型和结构类型
派生的声明器类型:数组类型,函数类型和指针类型
在C程序中,引用不同翻译单元中相同对象或函数的声明不必使用相同的类型。他们只需使用足够类似的类型,正式称为兼容类型。同样适用于函数调用和左值访问; 参数类型必须与参数类型兼容,并且左值表达式类型必须与所访问的对象类型兼容。
类型T
和U
兼容。
它们是相同的类型(由typedef引入的同名或别名)
它们是兼容的不合格类型的相同cvr合格版本
它们是指针类型,并指向兼容的类型
他们是数组类型,并且
他们的元素类型是兼容的,并且
如果两者都具有恒定的大小,那么大小是相同的。注意:未知边界的数组与兼容元素类型的任何数组兼容。VLA与任何兼容元素类型的阵列兼容。(自C99以来)
它们都是结构/联合/枚举类型,并且
(C99)如果用标签声明了一个,另一个也必须用相同的标签声明。
如果两者都是完整类型,则它们的成员必须完全对应数量,使用兼容类型声明并具有匹配的名称。
另外,如果它们是枚举,相应的成员也必须具有相同的值。
另外,如果他们是结构或工会,
相应的成员必须以相同的顺序进行声明(仅限结构)
相应的位域必须具有相同的宽度。
一个是枚举类型,另一个是枚举的基础类型
他们是功能类型,和
他们的返回类型是兼容的
它们都使用参数列表,参数的数量(包括使用省略号)是相同的,相应的参数具有兼容的类型
一个是旧样式(无参数)定义,另一个具有参数列表,参数列表不使用省略号,每个参数在缺省参数后都与相应的旧式参数兼容(在函数参数类型调整后)促销
一个是旧式(无参数)声明,另一个是参数列表,参数列表不使用省略号,所有参数(函数参数类型调整后)不受默认参数促销影响
该类型char
不兼容signed char
且不兼容unsigned char
。
如果两个声明引用相同的对象或函数并且不使用兼容的类型,则程序的行为是未定义的。
// Translation Unit 1struct S {int a;};extern struct S *x; // compatible with TU2's x, but not with TU3's x// Translation Unit 2struct S;extern struct S *x; // compatible with both x's// Translation Unit 3struct 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#includestruct s {int i;}; // compatible with TU3's s, but not TU2'sextern struct s x = {0}; // compatible with TU3's xextern void f(void); // compatible with TU2's fint main(){ f(); return x.i;}// Translation Unit 2struct s {float f;}; // compatible with TU4's s, but not TU1's sextern struct s y = {3.14}; // compatible with TU4's yvoid f() // compatible with TU1's f{ return;}// Translation Unit 3struct s {int i;}; // compatible with TU1's s, but not TU2's sextern struct s x; // compatible with TU1's x// Translation Unit 4struct s {float f;}; // compatible with TU2's s, but not TU1's sextern struct s y; // compatible iwth TU2's y // the behavior is well-defined: only multiple declarations// of objects and functions must have compatible types, not the types themselves
注意:C ++没有兼容类型的概念。声明在不同翻译单元中兼容但不相同的两种类型的AC程序不是有效的C ++程序。
不完整的类型是一种对象类型,缺少足够的信息来确定该类型对象的大小。不完整的类型可能会在翻译单元的某个位置完成。
以下类型不完整:
类型void
。这种类型无法完成。
未知大小的数组类型。它可以通过稍后声明指定大小来完成。
未知内容的结构或联合类型。它可以通过相同结构或联合的声明来完成,该声明稍后在相同范围内定义其内容。
类型可能必须在声明之外的上下文中命名。在这些情况下,使用类型名称,在语法上,它与类型说明符和类型限定符列表完全相同,后面跟着声明符(参见声明),就像用来声明单个对象或函数一样类型,除了标识符被省略:
int n; // declaration of an intsizeof(int); // use of type name int *a[3]; // declaration of an array of 3 pointers to intsizeof(int *[3]); // use of type name int (*p)[3]; // declaration of a pointer to array of 3 intsizeof(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 functionsizeof(int *(void)); // use of type name int (*p)(void); // declaration of pointer to functionsizeof(int (*)(void)); // use of type name int (*const a[])(unsigned int, ...) = {0}; // array of pointers to functionssizeof(int (*const [])(unsigned int, ...)); // use of type name
除了标识符周围的多余括号在类型名称中有意义并且代表“没有参数规范的函数”:
int (n); // declares n of type intsizeof(int ()); // uses type "function returning int"
类型名称用于以下情况:
cast
sizeof
复合文字 |
(自C99以来) |
---|---|
通用选择alignof alignas _Atomic(当用作类型说明符时) |
(自C11以来) |
复合文字
(since C99)
generic selection
alignof
alignas
_Atomic (when used as a type specifier)
(since 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
C11标准(ISO / IEC 9899:2011):
6.2.5类型(p:39-43)
6.2.6类型的表示(p:44-46)
6.2.7兼容型和复合型(p:47-48)
C99标准(ISO / IEC 9899:1999):
6.2.5类型(p:33-37)
6.2.6类型的表示(p:37-40)
6.2.7兼容型和复合型(p:40-41)
C89 / C90标准(ISO / IEC 9899:1990):
3.1.2.5类型
3.1.2.6兼容类型和复合类型