数组(array)
GESP 4级 C++ 数组核心考察知识点
以下为数组知识点的核心考察内容,按学习逻辑与考察频次分模块整理,覆盖核心重点与高频易错点。
一、数组的基础定义与语法规范
核心重点
- 二维数组的标准定义格式:
类型名 数组名[行长度][列长度];,这是C++中二维数组的唯一合法基础定义格式。 - 维度定义规则:二维数组定义时,必须显式指定列维度的大小,行维度可以省略;列维度是编译器计算元素内存偏移的核心依据,不可缺失。
- 数组下标规则:C++数组下标从0开始计数,而非从1开始。例如访问数组第2行第3列的元素,对应的下标为
[1][2]。 - 数组初始化规则:二维数组支持不完全初始化,未显式初始化的元素会被编译器默认初始化为0,无需每行都显式填充所有元素。
- 多维数组定义:三维及以上数组的定义遵循相同规则,最右侧的维度必须显式指定,左侧维度可根据初始化列表推导。
高频易错点
- 非法的二维数组定义,如
int a[3][]、int a[][],仅指定行维度或两个维度均不指定,会直接触发编译错误。 - 错误的元素访问语法,如
a[1,2]、a(1,2)、a{1}{2},只有a[行下标][列下标]是合法的二维数组元素访问格式。 - 误以为二维数组必须完全初始化,未给所有元素赋值就会编译报错,实际上不完全初始化是C++支持的合法语法。
二、数组的内存布局与地址计算
核心重点
行优先存储规则:C++中,一维、二维、多维数组在内存中均采用行优先的连续存储方式。
- 二维数组:先完整存储第一行的所有元素,再依次存储第二行、第三行,所有元素在内存中是完全连续的。
- 三维数组:先按第一维分块,每个块内按第二维行优先存储,最终所有元素在内存中连续排列。
- 元素地址计算公式:
对于元素类型为32位整型(占4字节)的二维数组arr[M][N],已知数组首地址为base,则元素arr[i][j]的内存地址为:目标地址 = base + (i * N + j) * sizeof(元素类型) - 指针算术运算规则:指向数组元素的指针,加减整数时,会按指针指向的元素类型大小进行内存偏移,而非简单的数值加减。例如
int* p指向数组首元素,p += 1后,地址会向后偏移4字节,指向数组的第二个元素。
高频易错点
- 误以为二维数组在内存中按列优先存储,导致元素地址计算错误。
- 混淆指针偏移的单位,将
p+1的偏移量误认为是数值1,而非元素类型的字节大小。 - 计算多维数组地址时,误用行维度代替列维度进行偏移计算,导致元素定位错误。
三、数组元素的访问方式
核心重点
数组元素支持下标访问与指针解引用访问两种完全等价的方式,核心等价规则如下:
- 基础下标访问:最常用的
arr[i][j]格式,直观清晰,是工程中的首选写法。 二维数组指针解引用访问:
arr[i][j]完全等价于*(*(arr + i) + j)。- 分步解释:
arr + i偏移i行,指向第i行的首地址;*(arr + i)取第i行的首地址,等价于arr[i];*(arr + i) + j偏移j列,指向arr[i][j]的内存地址;最终解引用得到元素值。
- 分步解释:
- 一级指针遍历二维数组:利用二维数组内存连续的特性,通过
int* p = &arr[0][0]获取数组首元素地址,此时arr[i][j]等价于*(p + i * 列数 + j)。
高频易错点
- 二维数组指针解引用时层级错误,忽略二维数组名是指向一维数组的指针,直接对
arr+i解引用后当作元素值使用。 - 用一级指针访问二维数组时,列数计算错误,导致元素定位偏差。
- 数组下标越界访问,超出数组定义的维度范围,触发未定义行为。
四、二维数组的函数传参规则
核心重点
二维数组作为函数参数传递时,必须显式指定列维度的大小,行维度可以省略,共有三种合法的传参形式:
- 完整指定二维数组的两个维度:
void func(int arr[3][4]); - 省略行维度,仅指定列维度:
void func(int arr[][4]); - 数组指针形式:
void func(int (*arr)[4]);,其中int (*arr)[4]代表指向长度为4的int型一维数组的指针,与二维数组名的类型完全匹配。
高频易错点
- 用二级指针
int** arr接收二维数组名,二维数组名是指向一维数组的指针,与二级指针类型不匹配,会导致元素访问异常,属于非法写法。 - 误以为二维数组传参必须指定所有维度的大小,实际上仅列维度为必填项,行维度可省略。
- 误以为函数参数中声明
int arr[][4]是非法写法,实际上这是C++标准支持的合法传参形式。
五、静态数组与动态数组的核心区别
核心重点
C++中可通过静态二维数组、动态一维数组两种方式模拟二维表格结构,二者的核心特性对比如下:
| 特性 | 静态二维数组(int arr[3][4]) | 动态一维数组模拟二维(int* arr = new int[12]) |
|---|---|---|
| 内存分配位置 | 栈内存 | 堆内存 |
| 空间释放规则 | 函数执行结束后自动释放,无需手动操作 | 必须手动使用delete[]释放,否则会造成内存泄漏 |
| 内存连续性 | 所有元素在内存中完全连续 | 所有元素在内存中完全连续 |
| 大小灵活性 | 数组大小必须是编译期常量,无法动态修改 | 数组大小可在运行时动态指定,灵活性更高 |
| 适用场景 | 数组大小固定、数据量较小的场景 | 数组大小动态变化、数据量较大的场景 |
高频易错点
- 误以为静态数组与动态数组都能自动释放内存,忽略堆上申请的动态数组必须手动释放。
- 误以为动态一维数组模拟的二维数组内存不连续,实际上
new申请的一维数组在堆上是完全连续的内存空间。 - 释放动态数组时遗漏
[],写成delete arr,导致释放不完整,触发未定义行为。
六、多维数组的遍历与数值计算
核心重点
- 三维数组的遍历需要三层嵌套循环,分别对应三个维度的下标,循环边界需与数组维度长度严格匹配,外层循环对应第一维,中层对应第二维,内层对应第三维。
- 多维数组的元素访问格式为
arr[i][j][k],分别对应三个维度的下标,可通过条件筛选对符合要求的元素进行累加、统计等操作。
高频易错点
- 循环边界设置错误,导致数组下标越界,触发未定义行为。
- 多维度条件判断时,下标组合计算错误,导致数值统计结果偏差。
七、高频易错判断题考点汇总
| 题目说法 | 正确/错误 | 核心原因 |
|---|---|---|
二维数组int a[3][4]在内存中按行优先连续存放 | 正确 | C++数组默认采用行优先的连续存储方式 |
int arr[3][]是正确的二维数组声明 | 错误 | 二维数组声明必须指定列维度,仅指定行维度属于非法写法 |
| 二维数组作为函数参数时,必须显式指定所有维度的大小 | 错误 | 仅列维度必须指定,行维度可以省略 |
函数参数声明为int arr[][4],无法在函数内通过arr[i][j]访问元素 | 错误 | 该声明是合法的二维数组传参形式,可正常通过下标访问元素 |
int arr[2][3] = {{1,2},{3}};属于非法代码,必须每行显式初始化所有元素 | 错误 | C++支持二维数组不完全初始化,未初始化元素默认置0 |
数组首地址为0x7ffee4065820,int* p = arr; p+=1;后p的值为1 | 错误 | 指针算术运算按元素类型大小偏移,p的值为第二个元素的内存地址,而非数值1 |
| 静态二维数组和动态数组申请的内存都能自动释放 | 错误 | 动态数组在堆上分配,必须手动释放,无法自动回收 |
评论已关闭