类型
1. 什么是类型
数据类型是一组性质相同的值集合以及定义在这个值集合上的一组操作的总称:
- “一组性质相同的值的集合”: 这定义了这种类型能表示什么(性质)。
int类型的值集合是整数,比如-100,0,42。它不能是3.14,也不能是"Hello"。char类型的值集合是字符,比如'A','!','\n'(换行符)。 - “定义在这个值集合上的一组操作”: 这定义了我们能对它做什么(约束)。 对于
int类型,我们可以进行+(加)、-(减)、*(乘)、/(除) 等数学运算。 对于字符串 (在 C 中是char数组),我们不能用 + 来连接它们,而是需要使用库函数,比如strcat()(拼接)、strcpy()(拷贝)。
2. C 的基本类型 (Basic Type)
2.1 字符类型 (Character Type)
charsigned char,unsigned charwchar_t,char16_t,char32_t
2.2 整数类型 (Integer Type)
charsigned char,short,int,long,long long__int128等实现定义的类型- 2 和 3 统称有符号整数类型
boolunsigned charunsigned short,unsigned,unsigned long,unsigned long long__uint128等实现定义的类型- 5,6 和 7 统称无符号整数类型
- 类型
size_t是实现定义的类型
2.3 浮点类型 (Floating-Point Type)
- 实浮点类型(表示一个实数):
float,double,long double - 十进制实浮点类型:
_Decimal32,_Decimal64,_Decimal128 - 虚数类型(表示一个虚数):
float _Imaginary,double _Imaginary,long double _Imaginary - 复数类型(表示一个复数):
float _Complex,double _Complex,long double _Complex
3. C 语言中的其他类型
3.1 类型 void
void 是一种不完整类型,表示“无可取值集合”。它通常出现在三种位置:函数返回类型、函数形参列表中的 void、以及 void * 通用指针。第一种表示函数不返回值;第二种表示函数不接受参数;第三种表示“可指向任意对象类型”,但在解引用前必须先转换为具体对象类型指针。
#include <stdlib.h>
void log_ready(void) {
/* ... */
}
int main(void) {
void *p = malloc(sizeof(int));
if (p == NULL) {
return 1;
}
*(int *)p = 42;
free(p);
return 0;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
在项目代码中,void * 适合做“抽象接口层的通用入口”,但实现层应尽快转换到具体类型,避免类型信息丢失导致的错误。
3.2 枚举类型
枚举类型由一组具名整数常量组成,用于表达有限状态集合。与“直接使用整数常量”相比,枚举在表达意图、控制非法状态输入和提升可读性方面更有优势。C23 开始可以为枚举声明固定底层类型;在早期标准中,底层类型由实现决定,只保证能够容纳全部枚举项。
enum state {
STATE_INIT = 0,
STATE_READY = 1,
STATE_STOP = 2
};2
3
4
5
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
当一组值是“封闭集合”时,优先使用枚举,而不是散落的宏常量。这是更符合长期维护的做法。
3.3 派生类型
- 数组类型
- 结构体类型
- 联合体类型
- 函数类型
- 指针类型
- 原子类型
4. 类型的大小和表示范围
4.1 位和字节
- 位:执行环境中的存储单元。它可以容纳一个“可以拥有两种状态”的对象。
- 字节:执行环境中的存储单元。它有“地址”,可以容纳基础字符集里的字符。
类型大小以“字节”为单位描述,而不是以“位”为单位直接描述。标准保证 sizeof(char) == 1,但一个字节包含多少位由 CHAR_BIT 决定,常见实现是 8。写可移植代码时,不要把“1 字节 = 8 位”当成无条件真理,而应在必要时使用 <limits.h> 中的宏进行约束与检查。
4.2 sizeof 运算符的一种用法
sizeof ( 类型名 )- 返回值类型为
size_t,值为此类型的大小,单位是字节。
sizeof 在编译期可求值(对变长数组除外),因此常用于计算对象布局与数组长度。工程里建议使用 sizeof *ptr 或 sizeof arr / sizeof arr[0] 这类“随类型变化自动更新”的写法,避免手写类型名导致维护时不一致。
int arr[10];
size_t n = sizeof arr / sizeof arr[0];2
运行结果:该代码块主要用于语法或结构说明,单独运行通常无终端输出。
4.3 整型占据空间的大小和能表示的范围
signed char/unsigned char:至少 8 位;(unsigned) short:至少 16 位;(unsigned) int:至少 16 位,常见实现为 32 位;(unsigned) long:至少 32 位;(unsigned) long long:至少 64 位。- 8 位的有符号整数,取值范围为 -128~127;8 位的无符号整数,取值范围为 0~255;
- 16 位的有符号整数,取值范围为 -32768~32767;16 位的无符号整数,取值范围为 0~65535;
- 32 位的有符号整数,取值范围为 -2147483648~2147483647;32 位的无符号整数,取值范围为 0~4294967295;
- 64 位的有符号整数,取值范围为 -9,223,372,036,854,775,808~9,223,372,036,854,775,807;64 位的无符号整数,取值范围为 0~18,446,744,073,709,551,615。
1==sizeof(char)≤sizeof(short)≤sizeof(int)≤sizeof(long)≤sizeof(long long)。size_t是一种无符号整数类型,至少 16 位。
4.4 浮点型占据空间的大小,能表示的范围和精度
- IEEE-754 详情参见 IEEE754.md
float:32 位,通常匹配 IEEE-754 binary32 格式。double:64 位,通常匹配 IEEE-754 binary64 格式。long double:实现定义,常见的实现为 128 位或 80 位。_Decimal32:32 位,匹配 IEEE-754 decimal32 格式。_Decimal64:64 位,匹配 IEEE-754 decimal64 格式。_Decimal128:128 位,匹配 IEEE-754 decimal128 格式。
本章内容对应 cppref 链接如下: