先上个前菜
🍕🍔🍟🌭🍿🧂🥓🥚🍳🧇🥞🧈🫓🥖🥯🥨🥐🍞🧀🥗🥙🥪🌮🌯🍖🍗🍚🍲🥘🎂🍨🥂
话说函数的调用,那到底是调用谁,又是用谁呢;或者是,谁调谁,又是谁用谁呢?
要解决这些问题,我们需要先去了解两个概念!
一、实际参数:
- 真实传给函数的参数,叫实参。
- 实参可以是:常量、变量、表达式、函数等。
- 无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
- 实参出现在主调函数当中,当函数调用时,主调函数把实参的值传送给被调函数的形参,从而实现函数间的数据传递。
举个例子,假设我们有一个名为add的函数,该函数接收两个整数作为实际参数,然后返回两个数的和。在调用该函数时,我们可以将两个整数作为实际参数传递,例如:
int x = 3, y = 5;
int result = add(x, y);
在这个例子中,x和y是实际参数,它们在调用add函数时作为参数传递。
二、形式参数
- 形参出现在被调函数当中,在整个函数体内都可以使用。形参在定义时编译系统并不分配存储空间,只有在调用该函数时才分配内存单元。
- 形参被函数调用结束之后内存单元就自动销毁了,因此形式参数只在函数中有效。
假设我们有一个名为add函数,其形式参数是两个整数,则函数头可能如下所示:
int add(int x, int y)
{
return x + y;
}
在这个例子中,x和y是形式参数,它们在函数定义中声明为接收两个整数参数。在函数被调用时,实际参数的值将被赋给形式参数。或者说是形参是实参的一份临时拷贝。
- 了解完这两个参数后,接下来就要进入正题了
硬菜上场
🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴🦴
函数的调用方式大概有两种:
- 1、是传值调用
- 2、是传址调用
他们有什么区别呢,我们去探讨一下!
一、传值调用
- 函数的形参和实参分别占用有不同内存块,对形参的修改不会影响实参!
- 就是函数调用时实参将数值传入给形参。值传递时,实参传给形参,其实形参是实参的一份临时拷贝
例如:设计一个函数,用于比较两个整数的最大值。
- 运行结果:
- 形参和实参分别占用有不同内存块,它们之间没有任何联系,各自在各自的地盘上玩。
- 当形参x、y判断完成后,get_max函数就返回得到的最大值。
二、传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外部的变量建立起正真的联系,也就是函数内部可以直接操作函数外部的变量。
示例:设计一个函数,交换两个整数的大小。
2.1、使用传值调用(错误示例):
- 有图有真相!
- 想要修改实参a、b的值,用传值调用是无法交换成功的!
- 实参传递给形参的时候,形参是实参的一份临时拷贝,对形参的修改是不会影响实参的!
- 因此,我们不能一条道走到黑!需要换一种方法。
2.2、使用传址调用(正确示例):
- 交换成功!
- 通过地址,去远程操控实参,让函数和函数外部的变量建立起正真的联系,使得函数内部可以直接操作函数外部的变量。
何时使用传值/传址调用呢?
简单的说,就是当传值调用解决不了问题时,就用传址调用。(这不是废话吗🤣 )
笔者认为:
- 如果函数内部实现的功能不会影响到外部的时候,可以用传值调用。例如上面的例子中,get_max函数的功能是获取最大值,然后返回给主函数,它并没有影响到或者说是去改变主函数或其它函数的值,所有可以去使用传值调用。
- 如果函数内部实现的功能会影响到外部的时候,就必须使用传址调用。例如swap函数,当它将形参交换后,是需要改变外部的主函数内的实参a、b的值的。此时只有用指针,才能将它们联系起来,去操作修改,这已经影响到或者说是改变了主函数或其它函数的值,因此只能用传址调用。
另外,不知大家有没有发现,其实上面的get_max函数中也是可以使用传值调用的,只需要对传入的地址解引用一下就行了
int get_max(int* x, int* y)
{
if (*x > *y)
return *x;
if (*x < *y)
return *y;
}
看到这里,各位有没有感受到指针的魅力呀!
那它有多重要呢?
博主特意去问了一下最近火爆的人工智能Chat GPT~
- 笔者之后也会去更新指针的相关知识,感谢各位大佬的支持,如果对你有帮助,请点赞关注加收藏,谢谢!
- 我们下期见!