返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >你知道C语言函数调用常用的2种方式吗
  • 257
分享到

你知道C语言函数调用常用的2种方式吗

C语言函数调用方式C语言函数调用C语言函数 2023-05-18 06:05:55 257人浏览 安东尼
摘要

目录区别原理用途总结本篇博客会讲解C语言函数调用的2种方式,分别是:传值调用和传址调用。这2种函数调用方式有什么区别呢?为什么会有不同的效果呢?分别有哪些用途呢?下面我会一一展开。

本篇博客会讲解C语言函数调用的2种方式,分别是:传值调用和传址调用。这2种函数调用方式有什么区别呢?为什么会有不同的效果呢?分别有哪些用途呢?下面我会一一展开。

区别

传值调用,即通过传递变量的值来调用函数。

传址调用,即通过传递变量的地址来调用函数。

比如,假设有2个变量a和b,对于变量a和b来说test(a, b)就是传值调用,test(&a, &b)就是传址调用。

原理

这时你可能很好奇:这2种调用方式的原理是什么呢?其实非常简单。

先举个传值调用的例子:

// 函数定义
int Add(int x, int y)
{
	return x + y;
}
// 调用
int a = 3, b = 5;
int sum = Add(a, b);

在上面的代码中,我们分别把a和b的值传递给了Add函数中的x和y。此时,我们称:a和b是“实际参数”,简称实参;x和y是“形式参数”,简称形参。传值调用的方式,会把实参的值传递给形参,也就是说,把a中的3传递给x,此时x就是3,把b中的5传递给y,此时y就是5。在Add函数内部,把x+y的值带回来,也就返回3+5的值,即返回8,再把返回值赋值给sum,sum就是8。

再举个传址调用的例子:

// 函数定义
int Add(int* p1, int* p2)
{
	return *p1 + *p2;
}
// 调用
int a = 3, b = 5;
int sum = Add(&a, &b);

以上就是典型的传址调用,但是很显然在这个场景下,我们只想“求和”,使用传址调用有点多此一举,但是还是分析一下原理:我们把a和b的地址传给了p1和p2,此时p1存储了a的地址,p2存储了b的地址,p1就指向了a,p2就指向了b。我们想在Add函数内部求和,就要先对p1解引用,拿到a的值,再对p2解引用,拿到b的值,再把拿到的a和b的值加起来返回,此时sum就被赋值为函数的返回值,即8。

以上只是非常粗略的带大家了解了传值调用和传址调用的区别。下面用一个经典的例子进行更加深入的讲解。这个例子就是:写一个函数,交换2个整数的值。

使用传值调用的方式,写出来的函数如下:

// 定义
void Swap(int x, int y)
{
	int tmp = x;
	x = y;
	y = tmp;
}

// 调用
int a = 3, b = 5;
Swap(a, b);

下面我通过调试的方式,来带大家看一下这个程序会如何执行。

代码即将执行Swap(a, b);,此时a的值是3,b的值是5。接下来执行这条语句:

代码来到第17行,此时a和b的值并没有交换?到底发生了啥?

重新开始调试,这次我进入到Swap函数内部看一眼。

按照前面的分析,此时x和y拿到了a和b的值,接下来进行交换:

代码执行到第10行,此时可以发现,x和y其实已经交换了,但是a和b并没有变化?这又是为什么呢?

此时再回到main函数,发现a和b的值并没有被交换。

发现这个问题后,我们可以干一件事,使用下面的代码,把a、b、x、y的地址打印出来:

#include <stdio.h>
void Swap(int x, int y)
{
	printf("&x = %p, &y = %p\n", &x, &y);
	int tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 3, b = 5;
	printf("&a = %p, &b = %p\n", &a, &b);
	Swap(a, b);
	return 0;
}

输出结果如下:

可以发现,当把a的值传递给x,把b的值传递给y时,x和y,a和b已经是不同的空间了,此时相当于,内存中有4个变量,分别是a、b、x、y,由于值传递,x的值和a相同,y的值和b相同,此时交换了x和y,对a和b的值并没有影响!所以函数调用结束后,a和b的值并没有交换。

这时,我们就可以总结:当我们使用传值调用,实参的值传递给形参后,形参只是实参的一份临时拷贝,改变形参的值并不影响实参的值!

那Swap函数的正确实现形式是怎样的呢?相信聪明的你已经想到了,使用传址调用就行了嘛!

// 定义
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
// 调用
int a = 3, b = 5;
Swap(&a, &b);

为什么以上的代码就能实现“交换”的效果呢?这就是传址调用的神奇之处!

分析一下:把a的地址传递给p1,把b的地址传递给p2,此时p1就指向了a,p2就指向了b,这时再对p1和p2解引用,就能把a和b的值给修改了!

我们还是通过调试来观察一下细节:

进入到函数内部:

再回到main函数:

成功交换了a和b的值!

用途

根据以上的讲解,可以总结一下传值调用和传址调用的用途:

  • 传值调用适用于不需要修改函数外部变量的场景。
  • 传址调用适用于需要修改函数外部变量的场景。

这是因为,传值调用时,形参是实参的一份临时拷贝,改变形参并不影响实参,所以在函数内部没有能力改变外面的变量的值;传址调用就不一样了,形参保存了函数外部变量的地址,就可以通过解引用的方式,修改函数外部变量的值了。

总结

1.传值调用适用于不需要修改函数外部变量的场景,因为函数内部变量和外部变量并没有建立联系,是独立的空间。

2.传址调用适用于需要修改函数外部变量的场景,因为函数内部存储了指向函数外部变量的指针,建立了联系,可以通过解引用的方式改变函数外部的变量。

以上就是你知道C语言函数调用常用的2种方式吗的详细内容,更多关于C语言函数调用的资料请关注编程网其它相关文章!

--结束END--

本文标题: 你知道C语言函数调用常用的2种方式吗

本文链接: https://lsjlt.com/news/211760.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作