c风格数组长度应使用sizeof(array)/sizeof(array[0])在编译期计算,但传入函数后退化为指针导致失效;推荐用std::size(c++17起)或改用std::array/std::vector。

用 sizeof 除法获取编译期已知大小的数组长度
对 C 风格数组(即栈上定义、大小在编译期确定的数组),最直接的方式是 sizeof(array) / sizeof(array[0])。它本质是靠类型信息计算总字节数与单个元素字节数的比值。
这个方法只在数组未退化为指针时有效 —— 一旦传入函数,array 就变成指针,sizeof 返回的是指针大小(通常是 8),结果完全错误。
- ✅ 正确场景:
int arr[] = {1, 2, 3, 4}; size_t n = sizeof(arr) / sizeof(arr[0]);→ 得到 4 - ❌ 错误场景:把
arr传给void foo(int a[]) { ... }后,在函数内用同样方式算,结果是8 / 4 = 2(64 位系统)或更离谱的值 - ⚠️ 注意
sizeof对std::array也适用,但没必要 —— 它自带.size()
用 std::size(C++17 起)替代手写除法
std::size 是标准库提供的安全封装,底层仍依赖 sizeof,但它做了重载和类型检查,能拒绝指针参数,避免低级误用。
- ✅ 支持 C 风格数组:
int arr[5]; auto n = std::size(arr);→ 类型安全,编译期常量 - ✅ 同时支持
std::array和std::vector(后者返回运行时大小) - ⚠️ C++17 之前不可用;若项目还在用 C++11/14,需自行封装或坚持用
sizeof+ 断言校验 - ⚠️ 不是所有编译器默认启用 C++17,确认编译选项含
-std=c++17或等效设置
函数参数里怎么安全拿到数组长度?
数组作为参数传入函数时,天然丢失长度信息。不能靠 sizeof,必须显式传递或改用容器。
- ✅ 推荐:改用
std::array或std::vector,它们自带.size()方法,语义清晰且无退化风险 - ✅ 若必须用原始数组,把长度作为额外参数:
void process(const int* data, size_t len),调用方负责传对 - ⚠️ 模板推导可“捕获”数组长度:
template<size_t n> void foo(int (&arr)[N]) { /* N 可用 */ }</size_t>,但仅限于接受具体数组类型,无法接受指针或std::vector - ⚠️ 别试图用
std::extent_v<decltype></decltype>在函数内恢复长度 —— 参数已是指针,decltype得到的是int*,extent为 0
为什么 std::vector::size() 和 std::array::size() 行为不同?
两者都叫 size(),但实现机制和性能特征完全不同:前者查成员变量(O(1) 运行时),后者是 constexpr 函数,展开为编译期常量。
- ✅
std::array<int> a; constexpr auto n = a.size();</int>→n是字面量,可用于模板非类型参数 - ✅
std::vector<int> v(5); auto n = v.size();</int>→n是运行时值,不能用于需要常量表达式的地方(如数组维度) - ⚠️ 有人误以为
std::vector的size()也是编译期可知,结果在std::array<int v.size></int>这类写法中触发编译错误 - ⚠️
std::vector容量(capacity())和大小(size())不是一回事,别混用
实际项目里最容易出问题的,是把栈数组传进函数后还下意识用 sizeof 算长度 —— 这个坑没有编译警告,只有运行时逻辑错乱。要么彻底转向 std::array,要么在接口设计阶段就约定好长度必须显式传递。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











