
系统梳理 C++ 数组、指针的类型表示
...大约 3 分钟
一、分类
1.1. 已知大小的数组(位于栈上)
| 一维 | 二维 | 三维 | |
|---|---|---|---|
| 变量声明 | int a[5] | int b[3][4] | int c[2][3][4] |
| 类型名 | int[5] | int[3][4] | int[2][3][4] |
| 占用空间 | 5 * sizeof(int) | 3 * 4 * sizeof(int) | 2 * 3 * 4 * sizeof(int) |
1.2. 动态数组(位于堆上)
| 一维 | 二维 | 三维 | |
|---|---|---|---|
| 变量声明 | int* a | int** b | int*** c |
| 类型名 | int* | int** | int*** |
| 占用空间 | sizeof(size_t) | sizeof(size_t) | sizeof(size_t) |
| 描述 | 指向 {int, int, ...} 的第一个元素的指针 | 指向 {int*, int*, ...} 的第一个元素的指针 | 指向 {int**, int**, ...} 的第一个元素的指针 |
| 释放内存 | delete[] a; | for (i) delete[] b[i]; | for (i) for (j) delete[] c[i][j]; |
省略号表示仅靠类型名无法确定数组的长度
1.3. 复合
二维
| 变量声明 | int (*p)[5] | int *p[5] |
|---|---|---|
| 类型名 | int (*)[5] | int *[5] |
| 本质 | 指针 | 数组 (大小: 5) |
| 占用空间 | 1 * sizeof(size_t) | 5 * sizeof(size_t) |
| 描述 | 指向 {int[5], int[5], ...} 的第一个元素的指针 | 指向{int*, int*, int*, int*, int*}的第一个元素的指针 |
三维
| 变量声明 | int (*p)[2][3] | int *p[2][3] |
|---|---|---|
| 类型名 | int (*)[2][3] | int *[2][3] |
| 本质 | 指针 | 数组 (大小: 2 * 3) |
| 占用空间 | 1 * sizeof(size_t) | 2 * 3 * sizeof(size_t) |
| 描述 | 指向 {int[2][3], int[2][3], ...} 的第一个元素的指针 | 指向{{int*, int*, int*}, {int*, int*, int*}, ...}的第一个元素的指针 |
隐式转换
由于数组可以看作是指针的一种特例, 因此数组可以隐式转换为指针 例如:
int [5]可以隐式转换为int*int [3][5]可以隐式转换为int*[5]- 但
int [3][5]不能隐式转换为int(*)[5] int [5][2][3]可以隐式转换为int*[2][3]
二、规则与理解
2.1. 拆解规则
foo [n] bar相当于有 n 个foo bar组成的数组foo * bar相当于指向foo bar构成的数组的指针
2.2. 运算规则
- 小括号 包围的有限拆解
- 方括号 优先级高于 星号
- 相同运算优先级, 则从中间向外拆解
2.3. 实例解析
按照此规则, 就可以用置换原理来很容易地理解数组的类型表示:
int[2][3](中间向外拆解)
=(int) [2] ([3])
={ int[3], int[3] }int**(中间向外拆解)
=(int) * (*)
={int*, int*, ...}int(*)[5](小括号改变运算顺序, 先拆解星号)
={ int[5], int[5], ... }int*[5](原有顺序, 先拆解方括号)
={ int*, int*, int*, int*, int* }int (*)[2][3](小括号改变运算顺序, 先拆解星号)
={ int[2][3], int[2][3], ... }int *[2][3](原有顺序, 先拆解方括号, 中间向外拆解)
={ int*[3], int*[3] }(原有顺序, 先拆解方括号)
={ {int*, int*, int*}, {int*, int*, int*} }int *(*)[3](小括号改变运算顺序, 先拆解星号)
={ int *[3], int *[3], ... }(原有顺序, 先拆解方括号)
={ {int*, int*, int*}, {int*, int*, int*}, ... }
注意
可以观察到 int *[2][3] 其实是 int *(*)[3] 的一个特例。
换句话说 int *[2][3] 可以隐式转换为 int *(*)[3]。
Powered by Waline v3.6.0
