C语言参数传递——值传递与地址传递

最近开始复(yu)习(xi)C语言,看到参数传递这里,又遇到了以前一直没有搞清楚的一个问题,我相信这个问题大家许多初学者也会遇到过,就是C语言函数的参数传递方式。
C语言中参数的传递有两种方式:
1)值传递
2)地址传递
3)数组作为函数参数
这里用两个例子来说明这两种方式的区别。

  • 值传递
int main(){
    int a=3;
    int b=4;
    printf("初始值a=%d,b=%d\n",a,b);
    exchange(a,b);
    printf("运行后a=%d,b=%d",a,b);
    return 0;
}
void exchange(int a ,int b){
   int temp;
   temp=a;
   a=b;
   b=temp;
}

运行结果:这里写图片描述

  • 地址传递
int main()
{
    int i,j,k;
    int data[100];
    int length=3;
   int a=3;
    int b=4;
    printf("初始值a=%d,b=%d\n",a,b);
    exchange(&a,&b);
    printf("运行后a=%d,b=%d",a,b);
}

void exchange(int  *a ,int *b){
    int temp;
    temp =*a;
    *a=*b;
    *b=temp;
}

运行结果:这里写图片描述

why?
老生常谈的问题了,我们预期的是ab的值会交换,但是并没有达到预期的效果,因为这个函数使用的是值传递。
我个人是这样的理解的
main函数中声明的ab两个变量,看作是计算机中的两个盘子A,B。A盘子中放的是“3”,B盘子中放的是“4”。
值传递的方式,只是把两个盘子中的东西作为参数传入,起到的是一种模板作用,函数收到这两个参数之后,会找到另外两个跟“3”“4”一样的东西,对这两个东西进行操作。而并不会改变main中原来两个盘子的值。而地址传递,就是把A,B这个两个盘子作为参数传过去了,进行的操作会影响到这个盘子里的东西。
换言之,我们去饭店点菜,有时大厅中能看到保鲜膜裹着的样品菜,我们指着桌上盛放“鱼香肉丝”的盘子告诉服务员我们要这个菜,厨师会另取相同的食材做出我们点的“鱼香肉丝”,而原本放在大厅里的样菜并没有动。----这是值传递。
相反,我们跟服务员说,我们就要这个盘子里的菜,这样厨师就直接烹饪了我们指定的盘子里的菜。----这是地址传递。

另外还看到一种引用传递,是c++语言中参数的传递方式,声明格式如下

void exchange(int &a,int &b){
/*操作*/
}

另外需要注意的是,C语言中使用地址传参,声明的格式是void function(int *a)
而调用的格式是:function(&a)
因为传递的参数是地址,所以在调用时候要有“&”取地址符号!

  • 数组作为函数参数
    1)数组元素作为函数参数,函数的声明没有什么差别,还是分为上述的两种方式:void function(int a);//值传递或者是void function(int *a);//地址传递,调用函数时分别采用function(a[2]);或者function(&a[2]);这种情况下,存在值传递与地址传递的不同,参考上述。
    2)数组名作为参数传递:
    例如function(int a[])
    调用函数:function(a);//这里a是一个数组名字
    用数组名做函数实参时,不是把数组元素的值传给形参,而是把实参数组的首元素的地址传递给形式参数,也就是说形参数组发生改变,会使实参数组发生同样的变化。换言之,函数进行的操作就是直接发生在传递进来的数组上的。
    下面举一个例子,对数组a中的数字进行排序
#include stdio.h
int main()
{
    int i;
    int n=6;
    int a[6]={7,5,3,4,12,54};
    for(i=0;i<n;i++) printf("%d ",a[i]);
    printf("\n排序之后\n");
    Sort(a,n);
     for(i=0;i<n;i++) printf("%d ",a[i]);
    return 0;
}

void Sort(int a[],int n){
    int i,j;
    int tmp=0;
    for(i=0;i<n;i++){
        for(j=0;j<n-1-i;j++){
            if(a[j]>a[j+1]){
                tmp=a[j];
                a[j]=a[j+1];
                a[j+1]=tmp;
                }
        }
    }
}

运行结果:这里写图片描述

可以看出,函数名作为参数时,所做的操作会直接影响原来的数组。

<think>好的,用户想了解C语言值传递地址传递的区别及使用场景。我需要根据提供的引用资料来整理答案。首先,引用1提到C语言主要通过值传递和指针实现的地址传递,而C++还有引用传递,但用户的问题集中在C语言,所以可以忽略C++部分。接下来,引用2中的代码示例展示了值传递地址传递的具体应用。比如,在fun函数中,传递的是a和b的值,函数内部修改x和y不会影响外面的a和b。而在fun2中,通过指针传递地址,修改*p会改变原变量a的值。这说明值传递是复制数据,而地址传递通过指针操作原数据。引用3详细比较了两者的不同点:传递内容、对原始数据的影响、使用场景、性能和语言支持。需要将这些内容结构化,分点说明区别,然后举例使用场景。用户可能需要明确的对比表格或分点说明,但问题中没有明确要求,所以用清晰的段落分述即可。同时,用户可能想知道何时选择哪种传递方式,比如保护数据时用值传递,需要修改数据或处理大对象时用地址传递。 需要确保回答符合系统指令:行内公式用$...$,独立公式用$$...$$,但C语言问题可能涉及较少数学公式,注意检查。另外,生成相关问题和引用标识。最后,检查是否有遗漏点,如值传递的性能问题,地址传递的效率优势,以及指针的使用方法。确保回答正确引用资料,并在末尾添加相关问题。</think>### C语言值传递地址传递的区别及使用场景 #### 一、核心区别 1. **传递内容** - **值传递**:传递参数的**副本**(如$fun(a, b)$中的$a$和$b$),函数内部操作不影响原始变量[^3]。 - **地址传递**:传递参数的**内存地址**(如$fun2(\&a)$中的指针),通过指针解引用(`*p`)直接修改原始数据[^2]。 2. **对原始数据的影响** - 值传递函数内修改参数仅影响副本,原始变量不变(如示例中`a`和`b`的值未改变)[^2]。 - 地址传递:通过指针操作直接修改原始数据(如`fun2`中将`a`从10改为300)[^2]。 3. **性能差异** - 值传递需复制整个数据,大型结构体或数组时效率低[^3]。 - 地址传递传递指针(固定4/8字节),适合处理大对象[^3]。 #### 二、使用场景 | **场景** | **值传递** | **地址传递** | |-----------------------|-------------------------------------|-----------------------------------| | 保护原始数据 | 防止函数意外修改(如计算数学公式) | 不适用 | | 修改外部变量 | 不适用 | 必须(如`scanf`输入、链表操作) | | 处理大型数据 | 低效(内存复制开销大) | 高效(仅传递指针) | | 函数返回值传递 | 直接返回简单类型(如`int`) | 返回指针或结构体地址 | #### 三、代码示例对比 ```c // 值传递:无法修改外部变量 void swap_value(int x, int y) { int temp = x; x = y; y = temp; // 仅交换副本,外部变量不变 } // 地址传递:成功交换外部变量 void swap_address(int *x, int *y) { int temp = *x; *x = *y; *y = temp; // 通过指针修改原始数据 } ``` #### 四、注意事项 - **指针安全性**:地址传递需确保指针有效性(如非空指针)。 - **数据封装性**:值传递更适合需要隔离副作用的场景(如数学运算函数)。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

There Is No Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值