C++ 中数组作为参数传递时,在函数中使用sizeof 为什么无法得到数组的长度
数组长度
在C++ 中并没有提供java,C#的size,length的数组长度。
int arr[10];
std::cout << sizeof(arr)/ sizeof(int) << std::endl;
数组作为参数传递
#include "iostream"
using namespace std;
int main() {
int arr[]={1,2,3,4,5};
cout<<sizeof(arr)/sizeof(int)<<endl; //输入的是 5
return 0;
}
定义一个函数
#include "iostream"
using namespace std;
int multiply(int arr[],int number){
cout<<sizeof(arr)/sizeof(int)<<endl; //输出的 是2
}
int main() {
int arr[]={1,2,3,4,5};
cout<<sizeof(arr)/sizeof(int)<<endl; //输入的是 5
multiply(arr,3);
return 0;
}
这时候在函数中 计算出来的长度 并不是数组真实的长度;
在 C++ 中,当数组作为函数参数传递时,sizeof
无法得到数组的长度的原因是数组会退化(decay)为指针。具体来说,数组名在作为参数传递时,编译器会将数组的地址(即指向数组第一个元素的指针)传递给函数,而不是整个数组本身。
分析
-
数组在参数传递中的退化
在函数参数中,int arr[]
或int arr[10]
实际上被编译器解释为int* arr
,这意味着在函数中访问arr
时,它只是一个指向数组首元素的指针,而不再是一个完整的数组。- 原数组的大小信息并不会被传递到函数中。
sizeof(arr)
的结果是指针本身的大小,而不是数组的大小。
例如:
void foo(int arr[]) { std::cout << sizeof(arr) << std::endl; // 输出指针的大小,例如 8(在 64 位系统上) } int main() { int arr[10]; foo(arr); }
在函数
foo
中,arr
是一个指针,不再是main
中的数组。因此sizeof(arr)
是指针大小。 -
函数参数声明的等价性
函数参数中声明int arr[]
和int* arr
是等价的,这就明确了传递到函数的是一个指针,而不是整个数组。例如:
void foo(int arr[]); // 等价于 void foo(int* arr);
-
数组本质与内存模型
- 静态数组在内存中是连续存储的,编译器在数组作用域内可以推导其大小,因此
sizeof
可以计算静态数组的总大小。 - 但是当数组退化为指针后,指针只存储了数组首地址,无法通过这个地址直接推断数组的大小。
- 这与动态分配数组类似:动态分配的数组通过指针访问,也没有内置的大小信息。
- 静态数组在内存中是连续存储的,编译器在数组作用域内可以推导其大小,因此
-
如何在函数中获取数组大小?
如果确实需要在函数中知道数组的大小,可以采用以下方法:- 显式传递数组大小:
void foo(int arr[], size_t size) { std::cout << "Array size: " << size << std::endl; } int main() { int arr[10]; foo(arr, sizeof(arr) / sizeof(arr[0])); }
- 使用模板(适用于静态数组):
模板可以捕获数组的大小信息:template <size_t N> void foo(int (&arr)[N]) { std::cout << "Array size: " << N << std::endl; } int main() { int arr[10]; foo(arr); // 输出 10 }
- 显式传递数组大小: