因为数组传参会退化为指针,sizeof(arr)返回指针大小而非数组总字节数;推荐用模板函数array_size通过引用绑定保留维度信息,编译期推导长度。
![c++数组作为形参后sizeof(arr)/sizeof(arr[0])算错怎么解决](https://img.php.cn/upload/article/001/221/864/179031187844624.png?x-oss-process=image/resize,p_40)
为什么 sizeof(arr)/sizeof(arr[0]) 在函数内失效
因为 C++ 数组作为形参传入函数时,会自动退化为指针,arr 不再是数组类型,而是 T*。此时 sizeof(arr) 返回的是指针大小(通常是 4 或 8 字节),不是原始数组总字节数,除法结果必然错误。
用模板推导数组长度(推荐)
让编译器在编译期捕获数组大小,避免运行时退化。关键在于用引用绑定数组,保留维度信息:
template <typename t size_t n>
size_t array_size(const T (&)[N]) {
return N;
}</typename>
调用时直接传数组名即可:
int a[] = {1, 2, 3, 4};
std::cout
- 只适用于真实数组(栈上定义、非 new 分配)
- 不能用于函数参数中已退化的
int*变量 - 若需支持 const 修饰,模板参数加
const T(&&)[N]即可
改用 std::array 或 std::vector
现代 C++ 更应避免裸数组。两者都自带 .size() 方法,语义清晰且无退化问题:
void f(const std::array<int>& arr) {
std::cout & vec) {
std::cout <ul>
<li>
<code>std::array</code> 适合编译期尺寸固定、无需动态扩容的场景</li>
<li>
<code>std::vector</code> 适合大小不确定或需增删元素的情况</li>
<li>二者传参建议用 const 引用,避免拷贝开销</li>
</ul>
<h3>如果必须用裸数组指针,就别依赖 <code>sizeof</code>
</h3>
<p>一旦形参声明为 <code>int arr[]</code> 或 <code>int* arr</code>,编译器就丢掉了长度信息。这时唯一可靠做法是额外传入长度参数:</p>
<pre class="brush:php;toolbar:false;">void process(int* arr, size_t len) {
for (size_t i = 0; i
- 这是 C 风格兼容写法,明确、可控
- 切勿在函数内对
arr做sizeof运算——它永远不是你想要的 - 若调用方本身也是从另一个函数接收的指针,那长度必须由上游明确传递,无法自动恢复
C++ 数组退化是底层机制决定的,不是 bug,但容易误用。真正麻烦的不是“怎么修”,而是“什么时候意识到它已经退化了”——尤其当函数签名看着像接受数组,实际却只收了指针。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











