传指针+显式size参数最稳妥,因数组传参自动退化为指针且无长度信息,sizeof得指针大小而非数组字节数,易致越界崩溃;引用传递仅适用于编译期固定大小。

传指针 + 显式 size 参数是最稳妥的做法
数组名在传入函数时自动退化为指向首元素的 int*(或对应类型)指针,编译器完全不检查长度。如果不额外传 size,函数内无法安全遍历——sizeof(arr) 得到的是指针大小(通常是 8),不是数组总字节数。
常见错误现象:循环越界、读到垃圾值、程序崩溃(尤其开启 ASan 时直接报 heap-buffer-overflow)。
-
void process(int* arr, int size)和void process(int arr[], int size)等价,后者只是语法糖,别误以为方括号里填数字能约束长度 - 调用时写
process(data, 5),不能只写process(data)—— 编译器不会帮你算长度 - 如果数组是栈上定义的,可用
sizeof(data)/sizeof(data[0])算 size,但该技巧在函数内部失效(因为此时arr是指针)
用引用传递可保类型和长度,但仅限编译期固定大小
当你确定数组大小在编译期已知(比如 int buf[256]),用引用避免退化,让编译器做静态检查。
典型使用场景:配置缓冲区、硬件寄存器映射、固定尺寸帧数据处理。
- 声明必须带长度,如
void handle(const int (&arr)[10]);若传入int x[8],编译失败 - 模板可泛化:
template<size_t n> void print(const int (&arr)[N])</size_t>,调用时自动推导N - 不能用于
new int[10]或std::vector——它们的大小在运行时才确定
别用 int arr[5] 这种形参写法
看起来像限定长度,实际毫无作用。C++ 标准明确说明:一维数组形参的方括号内数字被忽略,不参与类型系统,也不生成边界检查。
容易踩的坑:
- 写
void f(int a[3]),却传入int b[10]—— 编译通过,但函数内按 3 个元素访问,后 7 个元素被忽略或越界 - 误以为
arr[5]能触发编译错误来防止传错大小,结果 runtime 才崩 - 和 C 风格文档混淆,把注释当契约(比如注释写“size=5”,但代码没校验)
二维数组传参必须指定列数,一维同理要小心“降维”陷阱
虽然问题聚焦一维,但很多人从二维切回来时会惯性出错:以为 int arr[][3] 的写法能迁移到一维,写成 int arr[][]——这在 C++ 中非法。
根本原因在于内存布局:一维数组退化为指针,二维数组退化为“指向含 N 个元素的数组的指针”(即 int (*)[3]),列数不可省略是因为编译器需要知道每行跨度来计算 arr[i][j] 的地址。
所以一维场景下,真正要盯住的只有两点:传指针、带 size;其余任何想靠语法“锁死”长度的尝试,都会在链接或运行时暴露。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











