【C语言】自定义函数、函数的参数、调用函数、传参传址。

时间:2022-10-26 14:19:03

????write in front????   

????大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流????

????2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星Top100~阿里云专家博主 & 阿里云星级博主~掘金⇿InfoQ~51CTOP创作者(创作新人榜No.10)~[CSDN]周榜102﹣总榜1024 ⇿ 全网访问量35w+????

????本文由 謓泽 原创 发布在51CTOP 如需转载还请通知⚠

????个人主页-​謓泽51Ctop的博客​????

????欢迎各位→点赞???? + 收藏⭐️ + 留言????

????系列专栏-​謓泽51Ctop的分类_51CTO博客​????

✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本????

【C语言】自定义函数、函数的参数、调用函数、传参传址。

????????自定义函数

如果库函数能干所有的事情,那还要程序员干什么?

除了库函数,我们还可以编写自己的函数,拓展程序的功能。自己编写的函数称为自定义函数。所以更加重要的是自定义函数,如何去实现一个自定义函数。

自定义函数和库函数一样,有函数名,返回值类型(int & void)和函数参数(有参无参),但是不一样的是这些都是我们自己来设计的,这从而就给了程序员一个很大的发挥空间。

那我们举出一个例子:写一个函数判断两个数字大小!

#include<stdio.h>
int Max(int x, int{
if (x > y)
return x;
else
return y;
}
int main(void){
int a = 10;
int b = 20;

int ret = Max(a, b);
printf("ret = %d\n", ret);
return 0;
}

【C语言】自定义函数、函数的参数、调用函数、传参传址。

????运行结果↓

ret = 20    


那我们再举出一个无返回值类型例子:写一个函数交换两个值的变量!

#include<stdio.h>
void swap(int *x, int *y)
{
int tep = *x;
*x = *y;
*y = tep;
}
int main(void){
int a = 10;
int b = 20;
printf("交换之前:a=%d,b=%d\n", a, b);
swap(&a, &b);
printf("------------------\n");
printf("交换之后:a=%d,b=%d\n", a, b);
return 0;
}

【C语言】自定义函数、函数的参数、调用函数、传参传址。

????运行结果↓

交换之前:a=10,b=20

交换之后:a=20,b=10

注意→在你交换值的时候需要取出它们的地址,因为相当于你以及改变它们的内存编号了!我们指望它能够把ab的值进行交换,也就是说我们在这个过程中会把swap()函数的值进行交换。所以,我们的外部函数和内部函数是必须要建立联系。那么我们就要把地址给传递过去,通过地址的内存单元的编号我们才能够找回来。 


????????函数的参数

????实际参数(实参)

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

像上面示例当中 swap(&a,&b);     这里的swap()括号里面的变量就是实际参数。

????形式参数(形参) 

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元)调用一瞬间才会开辟内存空间,所以叫做形式参数。形式参数当函数调用完成之后就会自动销毁了。因此形式参数只是在函数当中有效!声明周期范围有限。

像上面的示例当中void swap(int *x, int *y) 这里的无返回类型swap函数里面就是形式参数。

形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参。


????????调用函数

创建 C 函数时,会定义函数做什么,然后通过调用函数来完成已定义的任务。

当程序调用函数时,程序控制权会转移给被调用的函数。被调用的函数执行已定义的任务,当函数的返回语句被执行时,或到达函数的结束括号时,会把程序控制权交还给主程序。就像我们上面举例说明的代码一样!

说的简单点,就是让这个函数帮我们做事情,叫做函数调用!

C语言中,函数的调用的一般形式为:

  • 函数名(实际参数列表)

函数的调用方式!!!

  1. 函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。例如:z=max(x,y)是一个赋值表达式,把 max的返回值赋值给 z。
  2. 函数语句:函数调用的一般形式加上分号即构成函数语句。例如:printf("%d",a); scanf ("%d",&b);都是以函数语句的方式调用函数。
  3. 函数实参:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。例如: printf  函数的实参来使用的。在函数调用中还应该注意的一个问题是求值顺序的问题。所谓求值顺序是指对实 参表中各量是自左至右使用呢,还是自右至左使用。对此,各系统的规定不一定相同。 printf 函数时已提到过,这里从函数调用的角度再强调一下。

当调用函数时,有两种向函数传递参数的方式,如下↓ 

????????传值调用

向函数传递参数的传值调用方法,把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。

  • C 语言使用传值调用方法来传递参数。一般来说,这意味着函数内的代码不会改变用于调用函数的实际参数。
  • 函数 swap() 定义如下
void swap(int x, int y)
{
int temp;
temp = x; /* 保存 x 的值 */
x = y; /* 把 y 赋值给 x */
y = temp; /* 把 temp 赋值给 y */
}

【C语言】自定义函数、函数的参数、调用函数、传参传址。

现在,让我们通过传递实际参数来调用函数 swap() ↓

#include <stdio.h>
void swap(int x, int{
int temp;
temp = x; /* 保存 x 的值 */
x = y; /* 把 y 赋值给 x */
y = temp; /* 把 temp 赋值给 y */

}

int main (void){
int a = 100;
int b = 200;

printf("交换前,a 的值: %d\n", a );
printf("交换前,b 的值: %d\n", b );

// 调用函数来交换值
swap(a, b);

printf("交换后,a 的值: %d\n", a );
printf("交换后,b 的值: %d\n", b );
return 0;
}

【C语言】自定义函数、函数的参数、调用函数、传参传址。

????运行结果↓  交换前,a 的值: 100 交换前,b 的值: 200 交换后,a 的值: 100 交换后,b 的值: 200

可以从上面的代码发现程序并没有达到交换的效果!

????????传址(引用)调用 

通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。 

  • 通过引用传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。
  • 传递指针可以让多个函数访问指针所引用的对象,而不用把对象声明为全局可访问。
  • 函数 swap() 定义如下:
void swap(int *x, int{
int temp;
temp = *x; /* 保存地址 x 的值 */
*x = *y; /* 把 y 赋值给 x */
*y = temp; /* 把 temp 赋值给 y */

【C语言】自定义函数、函数的参数、调用函数、传参传址。

现在,让我们通过传递实际参数来调用函数 swap():  

#include <stdio.h>

void swap(int *x, int{
int temp;
temp = *x; /* 保存地址 x 的值 */
*x = *y; /* 把 y 赋值给 x */
*y = temp; /* 把 temp 赋值给 y */
}

int main (void){
int a = 100;
int b = 200;

printf("交换前,a 的值: %d\n", a );
printf("交换前,b 的值: %d\n", b );

/* 调用函数来交换值
* &a 表示指向 a 的指针,即变量 a 的地址
* &b 表示指向 b 的指针,即变量 b 的地址
*/
swap(&a, &b);

printf("交换后,a 的值: %d\n", a );
printf("交换后,b 的值: %d\n", b );

return 0;
}

【C语言】自定义函数、函数的参数、调用函数、传参传址。

 ????运行结果↓

交换前,a 的值: 100 交换前,b 的值: 200 交换后,a 的值: 200 交换后,b 的值: 100

在讲以上知识点的时候,希望大家再写自定义函数的时候,我们自定义函数只需要完成我们的功能即可,不需要进行很多无谓的操作,这样只会显得多此一举。

在这里拓展一个知识点,假设你实参里面有数组名,那么我们把数组名传递给到形参里去的话。注意:我们传递的仅仅是数组首元素的地址!