数组指针 vs 指针数组 完整区别总结
一、核心本质完全不同
二、语法区分(括号优先级关键)
- int *arr[5]:[] 优先级高于 *,先结合成数组 arr[5],再修饰为 int * 类型,即存放int指针的数组。
- int (*p)[5]:() 强制让 * 和变量 p 结合,p 是指针;[5] 代表它指向包含5个int元素的数组。
三、内存占用(64位系统)
四、加减1时的地址偏移规则(最核心差异)
1. 指针数组元素 arr[i] + 1
arr[i] 是普通 int*,+1 偏移单个元素大小(4字节int / 1字节char) 例:char *p[5],p[0]+1 只向后走1字节,指向下一个字符。
2. 数组指针 p + 1
p 指向完整数组,+1 一次性偏移整个数组总字节数 例:int (*p)[5],数组总大小5*4=20字节,p+1 地址直接+20,跳到下一个同规格数组。
文档示例:
int a[5] = {1,2,3,4,5};
int (*p)[5] = &a; // &a是数组指针类型
p + 1; // 一次性偏移整个数组20字节
五、适用场景 & 二维数组配套用法
1. 指针数组:处理多个字符串、字符串列表
// 存放多组字符串常量,节省空间
char *str_arr[3] = {"aaa", "bbb", "ccc"};
// 传参对应形参:char *str_arr[] / char **str_arr
对比二维字符数组 char str[3][100]:二维数组存完整字符串,占用连续字符空间;指针数组只存地址,体积更小。
2. 数组指针:配合二维整型/字符数组传参
二维数组数组名 a 本身就是数组指针 int (*a)[列数]
int a[2][3] = {1,2,3,4,5,6};
// 函数形参两种等价写法,都要求固定列数
void print(int arr[][3], int row);
void print(int (*arr)[3], int row);
文档明确规则:二维数组传参必须指定列数,底层就是数组指针。
六、取值解引用结果
- arr:数组首地址,类型 int **(二级指针)
- arr[i]:第i个指针,类型 int *
- *arr[i]:指针指向的int数据
- p:数组整体地址,类型 int (*)[5]
- *p:等价于数组名 a,类型 int *(首元素地址)
- (*p)[i]:数组内第i个元素,等价 a[i]
七、快速对比表格


