数据类型 (C语言)
在C语言中,数据类型可以分为两类:基础数据类型和复合数据类型。
基础数据类型
注意:以下是典型的数据位长和范围。编译器可能使用不同的数据位长和范围。请参考具体的参考。
在标准头文件limits.h 和 float.h中说明了基础数据的长度。float,double和long double的范围就是在IEEE 754标准中提及的典型数据。另外,C99添加了新的复数类型,C11添加了原子类型,它们不在本条目讨论范围内。关于这些类型的具体含义和部分细节,参见资料类型,最后一列写出了这些类型在硬件层面的类型(x86&x86_64实现)
关键字 | 位元组(字节) | 范围 | 格式化字符串 | 硬件层面的类型 | 备注 |
---|---|---|---|---|---|
char |
1bytes | 通常为-128至127或0至255,与体系结构相关 | %c | 字节(Byte) | 大多数情况下即signed char;
在极少数1byte != 8bit或不使用ASCII字符集的机器类型上范围可能会更大或更小。其它类型同理。 |
unsigned char |
1bytes | 通常为0至255 | %c、%hhu | 字节 | |
signed char |
1bytes | 通常为-128至127 | %c、%hhd、%hhi | 字节 | |
int |
2bytes(16位系统) 或 4bytes |
-32768至32767或 -2147483648至2147483647 |
%i、%d | 字(Word)或双字(Double Word) | 即signed int (但用于bit-field时,int可能被视为signed int,也可能被视为unsigned int)
|
unsigned int |
2bytes 或 4bytes |
0至65535 或 0至4294967295 |
%u | 字或双字 | |
signed int |
2bytes 或 4bytes |
-32768至32767 或 -2147483648至2147483647 |
%i、%d | 字或双字 | |
short int |
2bytes | -32768至32767 | %hi、%hd | 字 | 即signed short
|
unsigned short |
2bytes | 0至65535 | %hu | 字 | |
signed short |
2bytes | -32768至32767 | %hi、%hd | 字 | |
long int |
4bytes 或 8bytes[1] |
-2147483648至2147483647 或 -9223372036854775808至9223372036854775807 |
%li、%ld | 长整数(Long Integer) | 即signed long
|
unsigned long |
4bytes 或 8bytes |
0至4294967295 或 0至18446744073709551615 |
%lu | 整数(Unsigned Integer)或
长整数(Unsigned Long Integer) |
依赖于实现 |
signed long |
4bytes或 8bytes |
-2147483648至2147483647 或 -9223372036854775808至9223372036854775807 |
%li、%ld | 整数(Signed Integer)或
长整数(Signed Long Integer) |
依赖于实现 |
long long |
8bytes | -9223372036854775808至9223372036854775807 | %lli、%lld | 长整数(Long Integer) | |
unsigned long long |
8bytes | 0至18446744073709551615 | %llu | 长整数(Unsigned Long Integer) | |
float |
4bytes | 2.939x10−38至3.403x10+38 (7 sf) | %f、%e、%g | 浮点数(Float) | |
double |
8bytes | 5.563x10−309至1.798x10+308 (15 sf) | %lf、%e、%g | 双精度浮点型(Double Float) | |
long double |
10bytes或 16bytes |
7.065x10-9865至1.415x109864 (18 sf或33 sf) | %lf、%le、%lg | 双精度浮点型(Double Float) | 在大多数平台上的实现与double 相同,实现由编译器定义。
|
_Bool
|
1byte | 0或1 | %i、%d | 布尔型(Boolean) |
注:粗体为C99所新增的类型。
复合数据类型
在C语言中,复合数据类型可分为三类:结构、联合和枚举。在现代C语言中,联合和枚举的使用频率已逐渐减少。
结构
结构(structure variable)允许构造由多个基础数据类型组合而成的复杂结构[2]。结构为面向对象编程的蓝本。以下示例通过结构和结构体里的指针实现了二叉树结构:
typedef struct Bintree {
int data;
struct bintree *lchild; // left child of the node
struct bintree *rchild; // right child of the node
} bintree; // 自定义 bintree 类型
为结构定义变量时通常会用到动态内存分配:
#define mktree() (bintree *)malloc(sizeof(bintree)) // 分配该结构所需的内存单元数量
bintree *tree;
tree = mktree(); // 分配到 tree 指针
tree->data = 1;
tree->lchild = mktree();
...
由于C语言不具备自动垃圾收集(Garbage Collection)功能,使用完毕后调用free(treePtr)
来释放之前通过malloc(size)
分配的内存。详见这里。
在C99标准中,还添加了名为伸缩型数组成员的特性[3],关于此特性的内容超出了该条目的介绍范围,若需了解更多信息可参见文档或其它材料。
联合
联合(union)与结构相类似,但不同的是,联合在某一特定时刻只有最后被使用的成员的值是确定的,因此一个联合只使用所有成员中所占空间最大的成员所使用的内存。然而,一些编译器可以通过编译参数或#pragma的方式强制联合使用与所有成员所占储存空间的和相等的储存空间,在这种情况下,除最后被使用的成员外,其余成员的值是未定义的[2]。以下给出了联合的一个声明:
union foo{
int bar;
double foobar;
};
foo.bar = 8;
foo.foobar = 3.14;
在这个例子中,假设使用32位平台编译,一个double变量占8字节,一个int变量占2字节(由上表得),则该联合所占大小即为double类型的大小——8字节。在这段程序执行完毕后,foo.bar的值是未定义的,而foo.foobar的值为3.14。
枚举
枚举(enumerated type)用来声明一组整数常量。默认情况下,枚举声明格式为enum type {value1,value2,...,valuen};此时value1,value2分别为0,1,直到n-1。事实上,枚举类型在C语言实现中是以int类型储存的[2]。以下是枚举的一个声明:
enum a { b , c , d };
在此之后,便可以以如下方式使用:
enum a foo;
foo = b;
if(foo != c) //等同于if(foo != 1)
{
do_something();
}
而此时的b,c,d分别为0,1,2。 另外,也可以手动为枚举列表中的常量赋值。下面是一个例子:
enum colour {red = 100,blue = 700,yellow = 200};
则此时red,blue,yellow的值分别为100,700,200.
需要注意的是,枚举在C和C++中所表现的行为有一些细微的差异。参见C与C++的兼容性。
参考文献
- ^ GCC、Clang 等实现中,64位代码的long类型为64位,而MSVC中则维持32位
- ^ 2.0 2.1 2.2 ISO/IEC 9899:2018 (PDF). [2020-06-10]. (原始内容存档 (PDF)于2020-07-22).
- ^ ISO/IEC 9899:1999 (PDF). [2020-06-15]. (原始内容存档 (PDF)于2018-01-11).