sizeof(数组名)返回整个数组字节数,sizeof(指针)返回地址大小(如64位下为8);数组名是常量、不可修改,指针是变量、可运算赋值;函数参数中数组必退化为指针,仅sizeof和&操作能保留数组类型。

sizeof(数组名) 和 sizeof(指针) 返回值完全不同
这是最直接、最不容易被绕晕的区分点。数组名不是指针变量,它代表的是整个数据块;而指针是变量,只存一个地址。
常见错误现象:sizeof(arr) 在函数内突然变小,误以为“数组传进去了”,其实早已退化为指针。
-
int arr[5] = {1,2,3,4,5};→sizeof(arr)是5 * sizeof(int)(通常 20 字节) -
int* p = arr;→sizeof(p)是指针大小(64 位系统下为8) - 函数参数写成
void f(int arr[])或void f(int* arr),两者等价,sizeof(arr)在函数体内永远是8(或4),不是原数组大小
&arr 和 &p 的类型截然不同
取地址操作能暴露本质:数组名带尺寸信息,指针变量不带。
使用场景:需要传递“整个数组类型”(比如模板推导、引用绑定、跨函数保持维度)时,必须用 &arr 或数组引用。
立即学习“C++免费学习笔记(深入)”;
-
int arr[5];→&arr类型是int(*)[5](指向含 5 个 int 的数组的指针) -
int* p = arr;→&p类型是int**(指向 int* 的指针) -
(&arr) + 1地址偏移5 * sizeof(int);(p + 1)偏移sizeof(int)—— 算术行为差异根源在此
数组名不可赋值、不可自增,指针可以
数组名是常量地址标记,不是左值;指针是变量,可读可写。
容易踩的坑:把数组名当普通指针用,写出 arr++ 或 arr = p,编译直接报错。
-
int arr[3]; arr++;→ 编译错误:lvalue required as increment operand -
int* p; p++;→ 合法,p指向下一个int -
int arr[3], brr[3]; arr = brr;→ 错误(C++11 起也不允许数组间直接赋值) - 若真要复制内容,得用
std::copy、memcpy或换成std::array
函数参数中数组名必然退化为指针
这是绝大多数混淆的源头:你写 void f(int arr[10]),编译器根本不认 [10],它就是 void f(int* arr)。
性能 / 兼容性影响:退化后丢失长度信息,调用方必须额外传大小,否则无法安全遍历。
- 正确做法:
void f(int arr[], size_t n)或更现代的void f(std::span<int> s)</int>(C++20) - 错误假设:
sizeof(arr)在函数内能拿到原数组长度 → 实际得到的是指针大小 - 例外情况:只有
sizeof、&、绑定到数组引用(如void f(int (&arr)[10]))时,数组名才不退化
真正难处理的不是“怎么用”,而是“什么时候它还是数组,什么时候它已经变成指针了”。& 和 sizeof 是仅有的两个能守住数组身份的操作符,其余所有上下文——包括函数调用、加减、解引用、比较——它都按 int* 对待。


















