数组名不是指针,但在多数表达式中会隐式转换为指向首元素的指针;sizeof(数组名)返回整个数组字节数,sizeof(指针)返回指针自身大小(如64位系统为8字节);&数组名得到指向整个数组的指针,类型为int(*)[n],而&指针得到二级指针;数组名是常量不可修改,指针是变量可重新赋值;仅在sizeof、&运算符及数组引用绑定时数组名不退化。

数组名不是指针,但多数表达式中会隐式转换为指向首元素的指针——这是最常被误解的点,也是所有问题的根源。
sizeof(数组名) 和 sizeof(指针) 返回值完全不同
这是验证二者本质差异最直接的方式。数组名携带类型大小信息,指针只存地址。
-
sizeof(arr)返回整个数组占用字节数(如int arr[5]在 64 位系统上通常是20) -
sizeof(ptr)返回指针变量自身大小(通常是8字节) - 一旦数组名退化为指针(比如传入函数),
sizeof就再也拿不到原始长度了
&arr 和 &ptr 的类型和行为差异极大
取地址操作能暴露底层类型区别:一个是“指向整个数组的指针”,一个是“指向指针变量的二级指针”。
-
&arr类型是int (*)[5](指向含 5 个int的数组),(&arr) + 1地址偏移5 * sizeof(int) -
&ptr类型是int**,(&ptr) + 1偏移的是指针变量本身大小(8字节) - 把
&arr赋给int**会编译失败,类型不匹配
数组名不能赋值或自增,而指针可以
数组名是常量标识符,不是变量;指针是可修改的变量。
-
arr++或arr = nullptr直接报错:error: lvalue required as increment operand -
ptr++、ptr += 2、ptr = &x全部合法 - 函数参数写
void f(int arr[])看似接受数组,实际形参是int*,arr已退化,无法用sizeof获取长度
多维数组名退化规则更易踩坑
二维数组名退化后不是 int**,而是 int (*)[N] —— 这一点几乎所有人初学时都错。
-
int mat[3][4],mat退化为int (*)[4](指向含 4 个int的数组),不是int** - 若声明
int** p = mat,编译失败:类型不兼容 - 正确做法是
int (*p)[4] = mat,或用一维视角处理:int* p = &mat[0][0] -
mat + 1跳过一整行(4 * sizeof(int)),而*(mat + 1)等价于mat[1]
真正容易被忽略的是:数组名只有在 sizeof、&、以及绑定到数组引用(如 int (&r)[5])这三种场景下才不退化。其余所有地方——包括函数调用、算术运算、解引用——它都表现为一个常量指针。这个“有条件的退化”机制,才是理解所有现象的关键。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











