指向固定大小数组的指针必须写成int (*p)[5],表示p指向含5个int的数组;需用&arr初始化,不能用arr(类型不匹配),且数组长度不可省略,否则无法支持正确指针算术。

指向固定大小数组的指针怎么写
直接写 int* p 不是“指向数组的指针”,而是“指向 int 的指针”,它无法体现数组长度信息,也不能直接用于数组名退化后的地址运算。真要定义“指向整个数组”的指针,语法必须带维度:int (*p)[5] 表示 p 是一个指向含 5 个 int 元素数组的指针。
常见错误是把 int* p = arr; 当成指向数组的指针——其实 arr 退化为首元素地址,p 指向的是第一个 int,不是整个数组。
int arr[5] = {1,2,3,4,5};- 正确声明:
int (*p)[5] = &arr;(注意取地址符&,因为arr本身不是指针类型) - 错误写法:
int (*p)[5] = arr;→ 编译失败,类型不匹配 - 验证:用
sizeof(*p)得到 20(5×4),说明 *p 确实是完整数组类型
为什么不能省略数组长度
C++ 要求指向数组的指针必须知道内层数组大小,否则无法做指针算术:比如 p + 1 应该跳过整个数组(5 个 int),而不是跳过 1 个 int。编译器靠这个尺寸决定偏移量。
这意味着你不能写 int (*p)[](不完整类型),也不能用 auto 推导出这种指针(auto p = &arr; 可以,但类型是确定的 int (*)[5],不是泛型)。
立即学习“C++免费学习笔记(深入)”;
- 支持的:
int (*p)[10]、char (*q)[256]、double (*r)[3][4](指向二维数组) - 不支持的:
int (*p)[]、int (*p)[N](N 是变量,非 constexpr) - 替代方案:C++11 起可用
std::array<int></int>配合普通指针或引用,更安全且可推导
指向数组的指针和数组引用的区别
两者都能保留数组维度信息,但语义不同:int (&ref)[5] 是引用,int (*p)[5] 是指针。引用不可重绑定,指针可修改;引用更常用于函数参数避免退化。
例如函数接收数组时:
- 用指针:
void f(int (*p)[5]) { /* 使用 *p 访问 */ }→ 必须传&arr - 用引用:
void f(int (&arr)[5]) { /* 直接用 arr */ }→ 可传arr,更自然 - 二者都不能接受
int*或动态分配的内存(如new int[5]),因为类型不匹配
实际使用中容易漏掉的细节
最常被忽略的是取地址操作——数组名本身不是指针类型,取地址才得到指向数组的指针。另一个坑是混淆 int (*)[N] 和 int [N]*(后者非法,C++ 不允许这种写法)。
- 初始化时必须用
&arr,不是arr - 解引用后得到数组类型,可进一步用下标:
(*p)[2]等价于arr[2] - 不能对
int (*)[N]做++p来遍历多个同型数组,除非它们在内存中连续布局(如二维数组第一维) - 调试时看类型:gdb 中
ptype p显示int (*)[5]才对;如果显示int *,说明声明或赋值错了
真正需要“指向数组的指针”的场景不多,多数时候用引用、std::span(C++20)或容器更稳妥。但理解它,才能读懂底层 API 或旧代码里的 extern int (*table)[16]; 这类声明。


















