内存存储布局
int *arr[3]
是一个指针数组,在内存中,arr
本身占据一块连续的内存空间,存放三个指针 arr[0]
、arr[1]
、arr[2]
。
arr[0]
指向一个长度为 2 的 int
数组,这 2 个 int
类型的数据在内存中是连续存储的。
arr[1]
指向一个长度为 3 的 int
数组,这 3 个 int
类型的数据在内存中是连续存储的,但与 arr[0]
指向的数组在内存位置上不一定连续。
arr[2]
指向一个长度为 4 的 int
数组,这 4 个 int
类型的数据在内存中是连续存储的,但与 arr[0]
和 arr[1]
指向的数组在内存位置上不一定连续。
代码实现累加操作
#include <stdio.h>
int main() {
int arr1[2] = {1, 2};
int arr2[3] = {3, 4, 5};
int arr3[4] = {6, 7, 8, 9};
int *arr[3] = {arr1, arr2, arr3};
int sum = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < (i == 0? 2 : (i == 1? 3 : 4)); j++) {
sum += arr[i][j];
}
}
printf("Sum of all elements: %d\n", sum);
return 0;
}
指针运算精准定位元素
- 对于
arr[i][j]
,首先通过 arr[i]
获取到第 i
个指针,该指针指向一个 int
数组。
- 然后通过
arr[i][j]
,相当于 *(arr[i] + j)
,在该指针指向的数组中偏移 j
个 int
类型的大小,从而精准定位到具体元素。
与常规二维数组在存储和访问上的本质区别
存储区别
- 常规二维数组:在内存中是按行连续存储的,例如
int a[3][4]
,所有 12 个 int
元素在内存中是连续排列的。
- 指针数组实现的不规则二维数组:各个子数组在内存中不一定连续,指针数组
arr
存放的是各个子数组的起始地址。
访问区别
- 常规二维数组:访问元素
a[i][j]
时,计算偏移量的公式是固定的,即 i * 列数 + j
,可以直接通过数组首地址加上偏移量定位到元素。
- 指针数组实现的不规则二维数组:访问元素
arr[i][j]
时,先通过 arr[i]
获取子数组的首地址,再在子数组内通过偏移 j
个 int
大小来定位元素,由于每个子数组长度不同,不能像常规二维数组那样使用统一的偏移量计算公式。