arr和&arr值相同但类型不同:arr是int,&arr是int()[5];+1时前者跳1个int,后者跳整个数组;sizeof(arr)返回数组总字节,sizeof(&arr)返回指针大小;传参时arr退化为指针,&arr需匹配int(*)[5]参数。

arr 和 &arr 的值相同但类型完全不同
打印 arr 和 &arr 通常会看到一样的十六进制地址,比如都是 0x7ffeed8a42d2。但这只是“碰巧重叠”——它们指向同一块内存起始位置,不代表语义等价。关键区别在类型:arr 在绝大多数上下文中自动退化为 int*(假设是 int arr[5]),而 &arr 的类型是 int(*)[5],即“指向含 5 个 int 的数组的指针”。类型不同,直接决定后续所有运算行为。
加 1 运算结果天差地别
这是最能暴露区别的实操点。对同一数组 int arr[5] = {1,2,3,4,5};:
-
arr + 1:跳过 1 个int,即 4 字节(32 位)或 8 字节(64 位),指向arr[1] -
&arr + 1:跳过整个数组,即5 * sizeof(int)字节(通常是 20 或 40 字节),指向内存中紧挨着arr之后的那块未知区域
一旦你把 &arr + 1 强转成 int* 再解引用,比如 *((int*)(&arr + 1)),行为就是未定义的——它不指向你期望的下一个元素,而是越界了。
sizeof 中的行为彻底分道扬镳
sizeof 是少数几个让 arr 不退化的场景:
-
sizeof(arr):返回整个数组字节数,如5 * sizeof(int) -
sizeof(&arr):返回的是指针本身的大小(通常是 8 字节),因为&arr是一个指针类型(int(*)[5]),不是数组 -
sizeof(&arr[0]):也返回指针大小(int*类型)
所以不能靠 sizeof(&arr) 来推断数组长度;它和 sizeof(arr) 完全不是一回事。
传参时 arr 会退化,&arr 必须显式匹配
函数参数里写 void func(int arr[]) 或 void func(int* arr),实际接收的都是 int*,arr 已经丢失全部长度信息。而要真正传递“整个数组”的概念,必须用 &arr 配合对应类型:
void func(int (*p)[5]) { /* 接收指向 int[5] 的指针 */ }
int arr[5] = {0};
func(&arr); // 正确:&arr 类型正是 int(*)[5]
如果误传 func(arr),编译器会报错:类型不匹配。这不是语法糖能绕过去的,是类型系统在强制你意识到——arr 和 &arr 根本不是同一种东西。
最容易被忽略的是:这种区别只在涉及取地址、sizeof、函数传参、指针算术时才暴露出后果;日常写 arr[i] 或传给 printf("%p", arr) 看不出差异,反而埋下理解隐患。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











