<p>因为数组形参本质是传首地址:int arr[]、int arr[10]、int* arr三者等价,均退化为指针,修改arr[i]直接影响原数组;但重赋值或移动arr只改变形参指针本身。</p>

为什么数组形参修改会改变实参?
因为数组作为函数参数时,int arr[] 和 int* arr 本质相同:编译器不复制数组内容,只传递首元素地址。函数拿到的是原数组的“门牌号”,所有下标访问(如 arr[0]、arr[i])都直接落在原始内存上。
数组形参的三种写法其实等价
这三种声明在函数参数位置完全等效,都会退化为指针:
void func(int arr[])-
void func(int arr[10])(方括号里的数字被忽略) void func(int* arr)
它们都不能在函数内用 sizeof(arr) 得到数组长度——结果是 sizeof(int*)(通常 8 字节),不是整个数组大小。想用长度必须额外传入 size 参数。
常见误判点:以为这是“值传递”
很多人看到 func(arr) 就默认是值传递,但数组名不是普通变量。它在传参时自动转换为指针,所以实际发生的是“地址值的值传递”——你传进去的是一个地址副本,但它指向的仍是原数组。因此:
立即学习“C++免费学习笔记(深入)”;
- 修改
arr[i]→ 改的是原数组元素 ✅ - 让
arr = nullptr→ 只改了形参指针本身,不影响调用方的arr❌ - 对
arr做算术(如arr++)→ 只移动形参指针,不影响实参 ❌
如何避免意外修改原数组?
如果函数逻辑本不该改动外部数据,但又用了数组参数,最稳妥的方式是加 const 限定:
void read_only(const int* arr, int size)void read_only(const int arr[], int size)
这样一旦在函数里写了 arr[0] = 42,编译器立刻报错:assignment of read-only location。注意:这里的 const 修饰的是指针所指向的内容,不是指针本身。
真正容易被忽略的是:数组参数的“不可见绑定”——它不像引用那样显式带 &,也不像指针那样强制写 *,但行为却和指针完全一致。写函数时若没意识到这点,就可能在调试时花半天找“谁偷偷改了我的数组”。


















