sizeof不能直接用于函数参数中的数组,因为形参会退化为指针,sizeof(arr)返回指针大小而非原数组字节数,导致sizeof(arr)/sizeof(arr[0])计算错误。

sizeof 不能直接用于函数参数里的数组
很多人写 sizeof(arr)/sizeof(arr[0]) 在函数里算元素个数,结果总是错的——因为形参 arr 实际是退化成指针,sizeof(arr) 返回的是指针大小(通常是 4 或 8),不是原数组字节数。
典型错误场景:
void foo(int arr[]) {
std::cout
- 只有在定义数组的作用域内(比如局部数组、全局数组、函数内声明的数组)才能用
sizeof正确求长度 - 传入函数后,除非用引用或模板保留类型信息,否则无法恢复数组长度
- C 风格字符串(
char[])同理,sizeof对形参无效
用模板推导数组长度最安全
让编译器在编译期推导数组类型,避免退化。这是 C++11 起推荐的做法:
template<typename t size_t n>
constexpr size_t array_size(T (&)[N]) {
return N;
}</typename>
调用时直接传数组名(不能是表达式或指针):
int a[5] = {1,2,3,4,5};
std::cout
- 函数参数写成
T (&)[N]表示“对 T 类型、长度为 N 的数组的引用”,类型完整保留 -
constexpr确保编译期计算,零开销 - 不支持动态分配内存(如
new int[5]),只适用于栈上或静态数组
std::array 比裸数组更靠谱
如果可以改用标准容器,std::array 自带 size() 成员函数,语义清晰且类型安全:
std::array<int> a = {1,2,3,4,5};
std::cout & a) {
std::cout <ul>
<li>
<code>std::array</code> 是聚合类型,<code>sizeof</code> 依然有效,但优先用 <code>.size()</code>
</li>
<li>长度是类型的一部分,不同长度的 <code>std::array</code> 类型不同,编译期检查更强</li>
<li>注意:不能用 <code>std::array</code> 接收 C 风格数组,二者类型不兼容</li>
</ul>
<h3>运行时数组(new/malloc)没法用 sizeof</h3>
<p>堆上分配的数组没有长度元信息,<code>sizeof</code> 对指针返回的是指针本身大小,和所指内容无关:</p>
<pre class="brush:php;toolbar:false;">int* p = new int[10];
std::cout
- 必须额外保存长度(比如用
std::vector,或自己维护一个size_t len) -
std::vector的.size()是唯一合理选择;裸指针 + 长度变量容易出错,不建议手动管理 - 别试图通过地址差值或 magic number 反推长度——不可靠,且违反抽象原则
真正要小心的不是怎么写 sizeof,而是搞清数组是否还保有类型信息;一旦退化成指针,就永远失去了长度。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











