You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数值传递底层原理:数组与普通变量传参差异问询

函数值传递的底层实现:数组 vs 普通变量的传参差异

这是个非常戳中C/C++传参本质的好问题——很多刚接触这门语言的开发者都会被数组传参的“特殊表现”搞晕。咱们一步步拆解你的疑问:

一、普通变量的「值拷贝」到底是怎么运作的?(对应你的Ex2)

先看你第二个示例里的普通变量传参:

void interChange(int a, int b) {
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}
int main() {
    int a = 5, b = 3;
    interChange(a, b);
    return 0;
}

当你在main里调用interChange(a, b)时,编译器会做这几件事:

  • 为interChange函数创建一个独立的栈帧(栈是程序运行时用来存储局部变量、函数调用信息的内存区域)。
  • 在这个新栈帧里,生成两个全新的局部变量a和b——注意,它们和main里的a、b只是名字相同,完全是两个不同的内存块。
  • 把main中a的值(5)拷贝到interChange栈帧的a里,把main中b的值(3)拷贝到interChange栈帧的b里。

函数内部交换的只是这两个局部变量的值,和main里的变量没有任何关系,所以函数执行完后,main里的a、b完全不会变。

你问的几个小问题:

  1. 为何普通变量是值拷贝而非传递地址?
    这是C/C++的默认设计:默认传参方式就是值传递,只有当你显式声明参数为指针(int* a)或引用(int& a)时,才会传递地址/引用。编译器处理值传递时,就是直接复制变量的内容到函数栈帧,不需要额外处理地址逻辑(除非你手动用&取地址)。

  2. 为什么main和interChange里的&a地址非常接近?
    这和栈的生长方向有关:大多数系统的栈是从高地址向低地址生长的。main函数先运行,它的局部变量会在栈上占据一块高地址区域;当调用interChange时,栈会向低地址方向扩展,为函数的局部变量分配空间。所以两个栈帧里的变量地址自然会比较接近——比如你看到的0x69fed8(main的a)和0x69fe80(interChange的a),后者地址更低,完全符合栈的生长规律。

二、数组传参的「特殊值传递」:为什么看起来像传指针?(对应你的Ex1)

再看第一个示例的数组传参:

void function(int arr[]) {
    cout << arr << endl; // 输出首个元素的地址
    cout << sizeof(arr); // 32位系统下为4字节(指针大小)
}
int main() {
    int vector[] = {1,2,3,4,5,6,7};
    function(vector);
    return 0;
}

这里的核心是:数组作为函数参数时,会自动「退化」为指向数组首元素的指针——不管你写的是int arr[]还是int* arr,编译器都会把它解析成int* arr。

那为什么说这还是「值传递」?因为传递的是指针的值——也就是数组首元素的地址。当你调用function(vector)时,编译器会把vector(数组名本身就是首元素的地址)的值拷贝到函数的arr参数里(这个arr是个指针变量,在32位系统里占4字节)。

所以你看到的现象就很好解释了:

  • 打印arr时,输出的是数组首元素的地址,和vector的地址一致,因为拷贝的就是这个地址值。
  • sizeof(arr)得到的是指针的大小,而不是数组的大小——因为arr已经是指针,不再是数组了,自然丢失了数组的长度信息。
  • 如果你在函数里修改arr[0],原数组的第一个元素会被改变——这是因为你通过指针直接操作了原数组的内存空间,但本质上还是值传递(传递的是地址的拷贝),只是这个地址指向了原数组的内存。

为什么数组不直接做全量值拷贝?

这是语言设计的权衡:如果数组很大(比如1000个int元素),拷贝整个数组会非常消耗内存和时间,效率极低。所以C/C选择了数组退化指针的方式,兼顾效率和语法简洁。如果真的要传递数组的副本,你可以把数组包装成结构体,或者在C里用std::array来实现。

三、核心区别总结

  • 普通变量值传递:传递的是变量内容的拷贝,函数内的修改只作用于函数栈帧里的新变量,完全不影响原变量。
  • 数组「值传递」:实际传递的是数组首元素的指针值,函数内可通过指针修改原数组内容,但本质仍是值传递(传递的是地址的拷贝),且数组参数会退化为指针,丢失长度信息。

内容的提问来源于stack exchange,提问作者Cătălina Sîrbu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:34:29