int arr[]和int arr在c++中完全等价,均被编译器视为int,不保留数组长度;需知大小时应使用引用模板、std::array或std::span。

函数参数写成 int arr[] 和 int* arr 在 C++ 中**完全等价**,编译器都当作 int* 处理,不会保留数组长度信息。真正有区别的,是「传入实际参数时你给的是什么」以及「你是否需要在函数内知道数组大小」。
为什么 int arr[] 参数不保留数组长度
因为 C++(继承自 C)的函数参数传递机制中,数组名作为参数会自动退化为指针——无论你写 int arr[10]、int arr[] 还是 int* arr,函数体内看到的都是一个 int*,sizeof(arr) 永远是指针大小(通常是 8),不是原数组字节数。
- 写
void f(int arr[10])→ 编译器悄悄改成void f(int* arr) -
arr[5]实际被翻译成*(arr + 5),和指针算术完全一致 - 所以
arr[100]不会报错(可能越界访问),编译器无法检查
什么时候必须用指针而不是中括号写法
当你需要明确表达「这个参数就是个地址,不暗示任何数组语义」,或要配合其他指针操作时,直接用 int* 更准确、不易误导。
- 接收动态分配内存的起始地址:
int* p = new int[100]; f(p);—— 此时int* p比int p[]更符合直觉 - 函数要修改指针本身(比如重分配):必须传
int**,而不能靠int arr[]实现 - 和 C API 交互时(如
fread(void*, ...)),类型一致性要求你用void*,而非带[]的假数组
想保留数组长度信息,得换写法
如果真需要编译期知道元素个数(比如做边界检查、模板推导、std::span 构造),就不能依赖形参的 [] 或 *,而要用:
-
template<size_t n> void f(int (&arr)[N])</size_t>:引用方式绑定具体数组,N可推导 -
std::array<int></int>:固定大小容器,size()可用,且不退化 -
std::span<int></int>(C++20):轻量视图,可接受数组、指针+长度、std::vector等,安全又灵活
例如:void g(std::span<const int> s) { if (!s.empty()) std::cout —— 这才是真正能防止裸指针误用的方式。</const>
容易踩的坑:以为 int arr[5] 参数能限制调用方传入大小
完全不能。下面这段代码合法且常见,但极其危险:
void bad(int arr[3]) {
std::cout <p>那个 <code>[3]</code> 只是注释,不是契约。C++ 不做运行时或编译时数组长度校验。真正要约束,得靠模板引用、<code>std::span</code> 或额外传入 <code>size_t n</code> 参数并手动检查。</p>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











