跳至主要內容

系统梳理 C++ 数组、指针的类型表示

Kamimika...大约 3 分钟C/CppC/Cpp数组指针类型笔记

一、分类

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* aint** bint*** 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. 实例解析

按照此规则, 就可以用置换原理来很容易地理解数组的类型表示:

  1. int[2][3] (中间向外拆解)
    = (int) [2] ([3]) foo=int,n=2,bar=[3]foo=int, n=2, bar=[3]
    = { int[3], int[3] }

  2. int** (中间向外拆解)
    = (int) * (*) foo=int,bar=foo=int, bar=*
    = {int*, int*, ...}

  3. int(*)[5] (小括号改变运算顺序, 先拆解星号) foo=int,bar=[5]foo=int, bar=[5]
    = { int[5], int[5], ... }

  4. int*[5] (原有顺序, 先拆解方括号) foo=int,n=5foo=int*, n=5
    = { int*, int*, int*, int*, int* }

  5. int (*)[2][3] (小括号改变运算顺序, 先拆解星号) foo=int,bar=[2][3]foo=int, bar=[2][3]
    = { int[2][3], int[2][3], ... }

  6. int *[2][3] (原有顺序, 先拆解方括号, 中间向外拆解) foo=int,n=2,bar=[3]foo=int*, n=2, bar=[3]
    = { int*[3], int*[3] } (原有顺序, 先拆解方括号) foo=int,n=3foo=int*, n=3
    = { {int*, int*, int*}, {int*, int*, int*} }

  7. int *(*)[3] (小括号改变运算顺序, 先拆解星号) foo=int,bar=[3]foo=int*, bar=[3]
    = { int *[3], int *[3], ... } (原有顺序, 先拆解方括号) foo=int,n=3foo=int*, n=3
    = { {int*, int*, int*}, {int*, int*, int*}, ... }

注意

可以观察到 int *[2][3] 其实是 int *(*)[3] 的一个特例。
换句话说 int *[2][3] 可以隐式转换为 int *(*)[3]

上次编辑于:
贡献者: wzh656
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.4.3