数组指针是指向整个数组的指针,类型包含数组维度信息;int (p)[5]声明指向含5个int的数组,必须用&arr初始化,不能用arr(类型不匹配),sizeof(p)返回指针大小,而sizeof(p)返回整个数组大小。

什么是数组指针,不是指针数组
数组指针是指向整个数组的指针,类型包含数组维度信息;而指针数组是存放多个指针的数组。混淆这两者会导致 sizeof 结果异常、指针算术错误或函数传参崩溃。
关键区别在于声明语法:int (*p)[5] 是数组指针(指向含 5 个 int 的数组),int *p[5] 是指针数组(含 5 个 int* 元素)。
-
(*p)的括号不能省——否则变成int *p[5],语义完全不同 - 数组指针的类型必须明确大小,如
[5]、[10];无法声明指向“未知大小数组”的指针(int (*)[]不可直接定义变量,仅可用于函数形参) - 用
decltype可辅助推导:若int arr[5];,则decltype(&arr)就是int (*)[5]
如何正确声明和初始化数组指针
必须用取地址操作符 & 对整个数组取址,不能用数组名(数组名退化为首元素指针,类型不匹配)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
int arr[4] = {1, 2, 3, 4};
int (*p)[4] = &arr; // ✅ 正确:&arr 类型是 int (*)[4]
int (*q)[4] = arr; // ❌ 错误:arr 是 int*,无法隐式转为 int (*)[4]
- 初始化时右侧表达式类型必须严格匹配,包括元素类型和长度
- 多维数组同理:对于
int mat[3][5],其地址类型是int (*)[3][5],但更常见的是指向行的指针int (*row)[5] = &mat[0]; - 动态分配的数组(如
new int[6])无法直接用于数组指针——它没有静态维度信息,只能用普通指针int*接收
数组指针在函数参数中的典型用法
当需要把整个数组(含尺寸)传入函数时,数组指针比普通指针更安全,能避免越界且支持 sizeof 获取真实大小。
void process(int (*arr)[3]) {
static_assert(sizeof(*arr) == 3 * sizeof(int)); // ✅ 编译期可知大小
for (int i = 0; i
- 形参写成
int arr[][3]等价于int (*arr)[3],但前者容易误导为二维数组指针 - 如果函数要处理不同长度的数组,需模板化:
template<size_t n> void f(int (&arr)[N])</size_t>更灵活,但这是引用,不是指针 - 注意调用方必须保证实参确实是对应长度的数组——C++ 不检查,错传会引发未定义行为
常见错误:混淆 int (*)[N] 和 int* 的行为差异
对数组指针做 ++ 运算,移动距离是整个数组大小;而对 int* 做 ++,只移动一个 int。
int x[2][3] = {{1,2,3}, {4,5,6}};
int (*p)[3] = &x[0]; // p 指向第一行
p++; // p 现在指向 &x[1],即第二行起始地址
int *q = &x[0][0];
q += 3; // q 现在指向 x[1][0],等价于 p 当前所指
-
sizeof(p)是指针大小(通常 8 字节),sizeof(*p)才是3 * sizeof(int) - 用
std::vector或std::array替代裸数组能规避多数这类问题,但底层接口或 ABI 交互仍可能要求数组指针 - 调试时若发现
p + 1地址跳过了 12 字节(3*sizeof(int)),说明你用对了;跳了 4 或 8 字节,大概率是声明错了
数组指针的语法约束紧、容错低,稍不留神就退化成普通指针。真正要用它的地方往往涉及 C 风格 API、内存布局控制或模板元编程,日常开发中优先考虑 std::span(C++20)或封装类。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










