因为数组名传入函数时退化为指针,sizeof(arr)返回指针大小(如8字节),而非原数组总字节数,导致无法通过sizeof(arr)/sizeof(arr[0])正确计算长度。

为什么 sizeof(arr) 在函数里算不出数组长度
因为数组名传进函数时,已经不是数组了,而是退化成指向首元素的指针。比如你写 void f(int arr[]),编译器实际看到的是 void f(int* arr)。所以在函数内部执行 sizeof(arr),得到的是指针大小(64 位系统上通常是 8),不是整个数组字节数;而 sizeof(arr[0]) 虽然还是 4(int 大小),但两者一除就完全失真。
你在 main() 里能用 sizeof(data)/sizeof(data[0]) 算出 5,是因为 data 是栈上定义的真实数组,类型完整;一进函数,类型信息就丢了。
int arr[N] 和 int (&arr)[N] 的区别在哪
前者是语法糖,形同虚设:哪怕你写成 int arr[100],编译器也完全忽略 100,照样当 int* 处理;后者是真正的数组引用,保留了长度 N,且支持模板自动推导。
-
template<size_t n> void f(const int (&arr)[N])</size_t>—— 编译期就知道N,能做静态检查,比如把 3 元素数组传给期望 5 元素的引用形参,直接报错 - 但只适用于编译期大小确定的栈数组,
new int[10]或std::vector都不适用 - 不能和指针混用:传
&arr[0]就崩,必须传数组名本身
不传长度会出什么具体问题
最常见的是越界访问,尤其在循环或 memcpy 场景下:
立即学习“C++免费学习笔记(深入)”;
- 写
for (int i = 0; i ,但实际数组只有 5 个元素 → 写坏相邻内存 - 用
strcpy(dest, src)处理非字符串数据,若src中间有\0,提前截断;若没\0,一直读到内存乱码处崩溃 - 对接硬件寄存器或协议缓冲区时,长度错一位可能触发设备异常或校验失败
这些错误往往不立即暴露,而是延迟到后续某次内存访问才崩,调试成本极高。
什么时候可以不显式传长度
仅限以下明确可控的场景:
- 处理 C 风格字符串:靠
'\0'结束,但前提是数据**保证以\0结尾**,且函数逻辑只依赖该约定(如strlen) - 固定协议字段:比如解析一个已知 16 字节 header 的网络包,长度硬编码为
16即可 - 封装在结构体里:如
struct Buf { int data[256]; size_t len; };,此时长度随数据一起传,不额外加参数
只要数组大小可能变化、来源不可控、或涉及内存安全边界,就必须把长度作为独立参数传——这不是啰嗦,是让调用方明确承担边界的契约责任。


















