C语言函数(2)--形参与实参的讲解与函数的调用

一. 函数的参数

接下来,我们来讲一讲函数的形参与实参的区别

1 实际参数(实参): 真实传给函数的参数,叫实参。 实参可以是:常量、变量、表达式、函数等。 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形 参。

2 形式参数( 形参 ): 形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内 存单 元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。

先来看一组代码:

//交换两变量的值
void swap1(int x, int y) {
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}
int main() {
	int a = 10;
	int b = 20;
	printf("a:%d ,b:%d\n", a, b);
	swap1(a, b);
	printf("a:%d ,b:%d\n", a, b);
	return 0;
}

 如图所示,主函数中,创建了两个变量,swap1为交换函数

        主函数通过传递实参a,b的值赋给swap1函数的形式参数x,y,那么x,y就会拥有a,b的值10,20,接下来就可以靠着之后的代码进行操作最终将完成的值数返回主函数的形参 。

 但是,我们可以看下图的代码结果

 发现a,b的值并没有发生交换,仍是以原来的形式进行打印

 通过调试我们可以发现几个问题:

     1.   当a,b传参进入函数后,x,y确实发生了变化,x=20,y=10,但它却没有将交换后的结果返回来。

        2.函数swap1的形式参数x,y开辟了新的空间,与实参a,b的存储地址不同。

通过分析后,代码对应的内存分配如下: 这里可以看到 Swap1 函数在调用的时候, x , y 拥有自己的空间,同时拥有了和实参一模一样的内容。 所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。  

        也就是说临时拷贝的变量是处在函数中的,函数又是局部范围,x,y一旦出了函数的作用域便会被销毁,所以他连证据都还没给队友留下来,就被敌人杀死了

其实有一种解决方法,之前我提到过指针的基本使用

通过创建指针变量去获取变量a的地址,然后就可以间接修改a的值 。

那么我们也可以用指针去接收函数的实参地址,从而间接修改,达到形参能够影响实参的作用!

void swap2(int* x, int* y) {
	int tmp = 0;
	tmp = *x;
	*x = *y;
	*y = tmp;
}
int main() {
	int a = 10;
	int b = 20;
	printf("a:%d ,b:%d\n", a, b);
	swap2(&a, &b);
	printf("a:%d ,b:%d\n", a, b);
	return 0;
}

 这样能不能够交换两变量的值?答案是肯定的。

 这次x,y接收的就不是a,b的值了,而是它们的地址,如图x与y的地址存放的是a,b的地址,这样通过地址与x,y关联,间接改变。结果:a=20,b=10.


二.函数的调用

1.函数的调用方式可以分为两类:

a.传值调用

b.传址调用

2.1 传值调用: 函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

2.2 传址调用 :传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操 作函数外部的变量。 

        通过刚才例子的讲解,我们发现swap1就是实参a,b传值给形参x,y;swap2就是实参a,b传地址给形参 x,y。

此时,又引出一个问题,何时使用传值调用,何时使用传址调用?

我们需要注意的是:

        当要做的函数是对实参本身进行改变时,就使用传址调用;若函数只是对实参的值做加减乘除之类的操作的话,便使用传值调用。

       

上图代码add这个函数便是只对实参的值进行其他的操作,不改变实参值本身。 

// .写一个函数,每调用一次这个函数,就会将 num 的值增加1。
void Add(int* p) {
	(*p)++;
}
int main() {
	int num = 0;
	Add(&num);//1
	printf("%d\n", num);
	Add(&num);//2
	printf("%d\n", num);
	Add(&num);//3
	printf("%d\n", num);
	Add(&num);//4
	printf("%d\n", num);

	return 0;
}

而上面这道题的代码就是需要函数的实参通过改变自身实现功能,使用传址调用 

以上就是对函数形参与实参的区别以及函数调用的讲解了。

                                                                                                                                未完,待续!

  • 35
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

橙予清的zzz~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值