sizeof计算数组长度仅适用于栈上原生数组,传入函数会退化为指针导致失效;推荐优先使用std::array或std::vector的size(),或c++17的std::size()。

用 sizeof 算数组长度只对栈上原生数组有效
很多人一上来就写 sizeof(arr) / sizeof(arr[0]),结果在函数参数里失效——因为数组传参会退化成指针,sizeof 返回的是指针大小(通常是 8),不是原始数组长度。
适用场景:仅限于定义在当前作用域的栈数组,比如 int arr[5] = {1,2,3,4,5};。一旦你把它传进函数,或者用 new int[5]、std::vector,这条路就走不通了。
- 64 位系统下,
sizeof(int*)是 8,而sizeof(int[100])是 400,两者完全不是一回事 - 如果误用于函数参数,除法结果可能为 1 或 2(取决于
int和指针大小关系),毫无意义 - 模板推导可绕过退化问题:
template<size_t n> void f(int (&arr)[N]) { /* 此处 N 可用 */ }</size_t>
std::end 和 std::begin 不是万能的“长度工具”
std::end 返回的是指向末元素后一位置的迭代器,它本身不等于长度;要算长度得配合 std::begin 做减法,而且仅对支持随机访问的容器(如 std::array、原生数组)才高效。
常见错误:对 std::list 或 std::forward_list 用 std::end - std::begin —— 编译不过,因为它们的迭代器不支持减法操作。
立即学习“C++免费学习笔记(深入)”;
- 对原生数组:
std::end(arr) - std::begin(arr)等价于sizeof(arr)/sizeof(*arr),但更泛型 - 对
std::vector,别用这个:直接调v.size(),std::end(v) - std::begin(v)虽可行但多此一举 -
std::end不能单独当“长度”用——它是个地址,不是整数
真正安全通用的做法:优先用容器自带的 size()
现代 C++ 中,只要不是非用原生数组不可,就该用 std::array 或 std::vector。它们的 size() 成员函数返回 size_t,类型明确、语义清晰、无退化风险。
区别很实在:std::array 是栈上固定大小,size() 编译期可知;std::vector 是堆上动态大小,size() 运行时查字段,常数时间。
-
std::array<int> a = {1,2,3,4,5}; a.size()</int>→ 编译期常量 5 -
std::vector<int> v = {1,2,3}; v.size()</int>→ 运行时返回 3,不会崩,也不依赖上下文 - 不要对裸指针调
size():没有这个成员,编译失败
为什么老代码还见得到 sizeof 算法?
因为嵌入式或性能敏感场景中,有时必须用原生数组,且禁止 STL;这时 sizeof 是唯一零开销手段——但它把责任全压给程序员:你得确保数组没退化、类型没被意外 typedef 替换、没和指针混用。
一个典型翻车点:typedef int Arr[10]; Arr* p;,你以为 *p 是数组,其实 p 是指针,sizeof(*p) 是 40,不是 10。
- 宏封装常见但危险:
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])),一旦传入指针就静默错 - C++17 起可用
std::size()(注意不是std::vector::size()),它对原生数组、std::array、std::vector都适用,是目前最推荐的统一入口 - 如果你还在手写
sizeof除法,先确认:这真是一段不能改用std::array的遗留代码吗?
事情说清了就结束









