<p>因为形参int arr[]在函数签名中被编译器自动重写为int* arr,sizeof(arr)测的是指针大小(如8字节),而非原数组总字节数;声明中的[N]仅作语义提示,不参与类型检查或边界校验。</p>

数组传参时 sizeof 为什么失效?
因为形参 int arr[] 在函数签名中根本不是数组类型,而是编译器自动重写为 int* arr。此时 sizeof(arr) 测的是指针大小(x86_64 下通常是 8),不是原数组总字节数。你在 main 里看到的 sizeof(data) 是 20,进函数就变成 8——这不是 bug,是 C/C++ 的语言规则。
int arr[N] 声明里的 N 会被编译器忽略
哪怕你写成 void func(int arr[10]),这个 10 对编译器毫无约束力:它不参与类型检查,不生成边界校验,也不影响 sizeof。你传 int x[3] 或 int y[100] 都能编译通过,函数内部依然只能拿到首地址。
- 这种写法纯属语义提示,和
int* arr完全等价 - 某些静态分析工具可能警告「声明尺寸与实参不匹配」,但标准 C++ 不强制
- 真正保留长度的方式是引用语法:
template<size_t n> void func(int (&arr)[N])</size_t>
为什么 C++ 不自动带长度?历史与设计取舍
C++ 继承了 C 的底层模型:数组就是连续内存块 + 起始地址,没有运行时元数据。加长度字段会破坏 ABI 兼容性、增加指针开销、违背「零成本抽象」原则。所以它把责任交给程序员——你要安全访问,就得自己管长度。
- 字符串用
'\0'是约定,不是语言特性;其他数组没这种默认哨兵 -
std::array和std::vector是后来补的高级封装,底层仍靠模板或动态分配存长度 - 裸指针接口(如系统调用、硬件驱动)至今要求显式传
size_t len,这是跨平台事实标准
最容易被忽略的陷阱:宏 ARRAY_SIZE 只在定义域有效
像 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 这种宏,在函数内部对形参使用会静默出错——它算出来是 8 / 4 = 2(假设 int 是 4 字节),而不是你期望的元素个数。
立即学习“C++免费学习笔记(深入)”;
- 该宏只对栈上定义的数组(如
int data[5])有效 - 一旦数组退化为指针(包括函数参数、
malloc返回值、全局数组名),宏就失效 - 调试时发现
ARRAY_SIZE(arr)总是返回 1 或 2,八成是误用在了形参上


















