声明指向数组的指针必须明确指定长度,如 int (*p)[5] = &arr;,其中 &arr 类型为 int(*)[5],与 int* 本质不同,不可隐式转换。

怎么声明指向数组的指针
C++里「指向数组的指针」和「指向元素的指针」不是一回事,容易混淆。比如 int arr[5],&arr 是类型为 int (<em>)[5]</em> 的指针,而 arr 或 &arr[0] 是 int。前者指向整个数组块,后者指向单个 int。
- 必须写明数组长度:
int (*p)[5] = &arr;,漏掉[5]就变成普通指针,编译器不会帮你猜 - 不能用
auto p = &arr;然后指望后面当int<em></em>用——类型是确定的,auto推导出的是int ()[5],强转才可能用错 - 函数参数里写
void f(int (<em>p)[5])</em>才能真正按「数组单位」移动指针(p + 1跳过 5 个int),写成int p就只是跳 1 个int
访问数组成员时下标怎么算
用指向数组的指针访问成员,本质是先解引用再用下标:(*p)[i]。它等价于 arr[i],但逻辑上多了一层间接。
-
p[i]是错的——p指向的是「整个数组」,p[0]是第一个数组(即原arr),p[1]是紧邻其后的另一个 5 元素数组(如果内存里真有) - 正确写法只有两种:
(*p)[i]或p[0][i](因为p[0]解引用后就是原数组名,支持下标) - 如果误写成
p[i][j],那是在处理二维数组(比如int a[3][5]),此时p应为int (*)[5],且p[i]才是第 i 行
为什么 int* p = &arr 会报警告甚至报错
这是最常踩的坑:&arr 类型是 int (<em>)[5]</em>,而 int 是完全不同的类型,C++ 默认不隐式转换。
- 编译器通常报错类似:
cannot convert 'int (<em>)[5]' to 'int</em>' in initialization - 即使加
-fpermissive强行编译,后续p + 1会只偏移 4 字节(假设int为 4 字节),而你本意可能是跳过整个数组(20 字节) - 唯一安全的转换方式是显式 reinterpret_cast:
int<em> q = reinterpret_cast<int</em>>(&arr);,但你要清楚自己在绕过类型系统,且仅当确认内存布局连续、无 padding 时才合理
什么时候该用指向数组的指针而不是普通指针
它不是日常首选,只在特定场景有价值:
立即学习“C++免费学习笔记(深入)”;
- 处理固定大小的缓冲区组,比如网络协议中多个
char[64]包,用char (*pkts)[64]遍历时自然按包对齐 - 写模板或 SFINAE 判断数组维度时,
decltype(&arr)能保留长度信息,decltype(arr)是数组类型,decltype(arr+0)就只剩int* - 和 C API 交互时,某些函数明确要求
int (*)[N](如 OpenGL 的glUniformMatrix4fv中的value参数若传二维数组地址,需匹配列主序理解)
数组指针的尺寸和行为完全依赖字面长度,少写一个数字、多套一层括号,类型就变了。它不像引用或 std::array 那样带运行时保护,全靠你在声明那一刻写对。











