sizeof(arr)/sizeof(arr[0])仅对栈上定义的原生数组有效;传参后退化为指针、new分配、extern声明均失效;std::array支持安全size()。

用 sizeof 除以元素大小只对栈上数组有效
这是最常被误用的“公式”:sizeof(arr) / sizeof(arr[0])。它**仅在 arr 是真正的数组(非指针)且定义在当前作用域内时才正确**。一旦数组退化为指针(比如传入函数后),sizeof(arr) 就变成指针大小(通常是 4 或 8),结果完全错误。
常见错误场景:
- 把数组作为参数传给函数,函数内用该公式 → 得到 1 或 2(取决于平台),不是真实长度
- 用
new动态分配的数组 →sizeof返回指针大小,不是所分配内存大小 - 全局数组在另一个文件中声明为
extern int arr[];→ 编译器不知道长度,sizeof编译失败
std::array 是唯一能安全用 size() 的原生数组包装
如果你能控制数组定义方式,优先用 std::array:它保留长度信息,支持 .size(),且不带堆分配开销。
std::array<int, 5> arr = {1,2,3,4,5};
std::cout << arr.size(); // 输出 5,类型安全,编译期可知
注意:std::array 的大小必须是编译期常量,不能是变量。它的模板第二个参数就是长度,不是推导出来的。
立即学习“C++免费学习笔记(深入)”;
函数内无法直接获取传入数组长度,必须显式传参或改用 std::vector
C++ 没有“函数内自动获知数组长度”的机制。以下写法都不可靠:
-
void f(int arr[]) { ... }→arr是int*,无长度信息 -
void f(int arr[10]) { ... }→ 语法糖,实际仍是int*,10 被忽略
可靠做法只有两种:
- 额外传一个
size_t n参数(C 风格习惯) - 改用
std::vector或std::span(C++20),它们自带.size()
例如:void f(const std::vector<int>& v) { std::cout —— 安全、通用、推荐。</int>
模板推导可捕获栈数组长度,但仅限于函数模板实参
利用模板参数推导,可以写出只接受真正数组的函数:
template <size_t N>
void f(int (&arr)[N]) {
std::cout << N; // 正确输出长度
}
这个函数只能接收栈上定义的数组(如 int a[7]; f(a);),不能接收指针、std::vector 或动态数组。一旦你尝试 f(ptr),编译直接报错 —— 这其实是种保护机制,提醒你类型不匹配。
这种写法适合工具函数或断言场景,但别指望它解决所有“求数组长度”的需求。
实际项目里,绝大多数所谓“求数组长度”的需求,本质是想避免手动传长度。真正靠谱的做法是:用std::vector 替代裸数组,或用 std::span 包装已有数组并显式传递范围。裸数组的长度信息太容易丢失,不是靠一个“公式”就能补救的。











