当前位置:   article > 正文

【C语言】函数基础知识点总结_c语言函数知识点总结

c语言函数知识点总结

目录

1.函数定义

2.函数类型

2.1自定义函数

2.2库函数

3.实参与形参

4.函数的调用

5.函数的声明

6.函数的嵌套调用和链式访问

6.1嵌套调用

6.2链式访问

7.函数递归


博主水平有限,文章中若有错误,望读者们斧正。

1.函数定义

维基百科中,函数的定义是

“在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method,
subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组
成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软
件库。”
以上定义很好的说明了函数的特性:相对的独立性,对过程的封装和细节的隐藏。以后我们在做项目时,对函数的使用可以说是无处不在,甚至没有函数我们难以完成整个项目。由此可见学习函数是非常有必要的,下面我们开始函数的学习吧。

2.函数类型

c语言中函数分为两类:1.自定义函数 ,2.库函数

2.1自定义函数

函数在c语言中是可以自定义的,那如何定义一个函数呢?

  1. void fun_name(int x)
  2. {
  3. 函数语句;
  4. }

1)void是函数返回类型(如果函数在运行完成后需要给主程序返回一个值,我们就要用相应的类型去定义这个函数。要返回整形,就用 int去定义函数,不需要返回我们就用void类型)

2)fun_name是函数的名字,名字要起的与函数功能匹配

3)括号里的int是参数类型,x是函数参数(参数可以有一个或多个,但参数要尽量少),当然也可以没有参数,让程序直接运行函数的语句

  1. void test()
  2. {
  3. 函数语句;
  4. }

4)如果函数有返回值,调用函数时我们要创建一个变量接收返回值。没有变量时,我们直接调用就行 

  1. //1有返回值时
  2. int fun(int x)
  3. {
  4. 语句;
  5. }
  6. int main()
  7. {
  8. int a = 0;
  9. int ret = fun(a);
  10. return 0;
  11. }
  12. //2没有返回值时
  13. void fun(int x)
  14. {
  15. 语句;
  16. }
  17. int main()
  18. {
  19. int a = 0;
  20. fun(a);
  21. return 0;
  22. }

我们举一个例子:自定义一个函数,找出两个数中的最大值。那我们接下来就要创建一个有两个参数的函数,并且函数将会返回两个数中的最大值,返回值是整形,所以我们用 int类型创建一个名为Max的函数。要怎么调用我们创建的函数呢?我们只要写上函数名,再将要求最大值的两个数以逗号间隔,放进括号中

Max(a, b)
  1. //找出两个数中的最大值
  2. int Max(int x, int y)//设定两个函数参数
  3. {
  4. return (x > y ? x : y);
  5. }
  6. int main()
  7. {
  8. int a = 10;
  9. int b = 20;
  10. //当程序运行到这时,函数会被程序调用
  11. //函数返回最大值,我们创建 max 变量接收最大值
  12. int max = Max(a, b);
  13. printf("%d", max);
  14. return 0;
  15. }

这样Max 函数就写好了。 

2.2库函数

如果我们想实现一些基础功能(例如打印信息,计算字符串的长度,计算x 的k次方)我们还要自己写函数吗?当然是不用的,这样一来我们写代码的效率有太低了,什么都要自己写。所以c语言为我们提供了一系列的库函数,这些库函数很好地提高了我们代码的效率。
关于库函数,我们可以通过下面这几个网站来学习。

cplusplus.com - The C++ Resources Network

cppreference.com(英文)
cppreference.com(中文)
在这些网站中我们能查阅到库函数的基本信息,我们通过printf函数在cplusplus中的描述,看懂这些网站是怎么描述一个函数的,然后 举一反三,更好的学习其他函数
(函数名与函数功能)

红色框为函数原型,我们可以从中了解到函数的参数类型,返回类型,这个非常重要,决定了我们要给函数传参的类型以及要用什么类型接收返回值。
如果函数参数较多,介绍的Parameters中会具体说明每个参数的意思。这里举strcpy这个例子

 (函数返回类型与应用举例)

函数在不同情况下会返回不同的值,在Return Vaule中都具体介绍了。如果看完后还是不懂要怎么使用这个库函数,我们还能通过Example,看看别人是怎么使用这个函数的。 

 最后我们在使用库函数时一定要引用头文件。可以看到,printf的头文件是熟悉的stdio.h,我们就要在程序开始处加上#include<stdio.h>(这里建议把头文件都写在开头处)

 3.实参与形参

在函数中 x,y被称作形式参数(形参),a,b则是实际参数(实参)

结合刚刚的Max函数理解形参与实参

  1. //找出两个数中最大值
  2. int Max(int x, int y)
  3. {
  4. return x > y ? x : y;
  5. }
  6. int main()
  7. {
  8. int a = 10;
  9. int b = 20;
  10. int c = Max(a, b);
  11. printf("%d", c);
  12. return 0;
  13. }

它们有什么区别?形参其实是实参的一份临时拷贝。换言之,形参不等于实参,在函数运行时,程序为形参单独开辟内层空间,在程序结束时,程序销毁形参。两者的内存空间不同,所以改变形参的值不能改变实参。

我们再来一个例子

  1. void Swap(int x, int y)
  2. {
  3. int z = x;//两数交换时创建第三个变量,就像交换酱油与醋,我们要找第三个瓶子
  4. x = y;
  5. y = z;
  6. }
  7. int main()
  8. {
  9. int a = 10;
  10. int b = 20;
  11. printf("打印前:a = %d,b = %d\n", a, b);
  12. Swap(a, b);
  13. printf("打印后:a = %d,b = %d\n", a, b);
  14. }

这是一个交换函数,用它我们交换a与b的值,那结果是什么?

两个数没有发生交换,为什么?这是因为形参是实参的临时拷贝,改变形参的值不能改变实参的值。要实现两数交换,我们可以把地址传给形参,对地址解引用,找到实参,从而间接的改变实参。

4.函数的调用

把地址作为实参传给形参的调用函数方式称为传址调用,把实参的值作为实参传给形参的方式叫做传值调用。

来看看交换函数的正确写法

  1. void Swap(int* x, int* y)
  2. {
  3. int z = *x;
  4. *x = *y;
  5. *y = z;
  6. }
  7. int main()
  8. {
  9. int a = 10;
  10. int b = 20;
  11. printf("打印前:a = %d,b = %d\n", a, b);
  12. Swap(&a, &b);
  13. printf("打印后:a = %d,b = %d\n", a, b);
  14. }

运行结果 

 所以在写函数时要先考虑调用方式是传值调用还是传值调用。要想通过函数改变外部变量的值,我们通常传址调用,反之我们就使用传值调用。

5.函数的声明

如果我们在调用函数时,将函数写到了主函数的后面,程序会报一个警告,因为程序在运行时总是从上到下运行的,程序要调用一个函数,但是它却不认识这个函数,更不要说去调用它了。所以我们在调用函数时要满足先声明后使用,声明就是告诉程序这个函数叫什么,返回类型是什么,参数有什么...而声明一般会放到头文件中。(这里先简单介绍下,之后我会接着补充怎么具体声明)

  1. #include<stdio.h>
  2. //这就是声明Swap函数的格式
  3. void Swap(int* x, int* y);
  4. int main()
  5. {
  6. int a = 10;
  7. int b = 20;
  8. printf("打印前:a = %d,b = %d\n", a, b);
  9. Swap(&a, &b);
  10. printf("打印后:a = %d,b = %d\n", a, b);
  11. }
  12. //把Swap函数放在主函数的后面
  13. void Swap(int* x, int* y)
  14. {
  15. int z = *x;
  16. *x = *y;
  17. *y = z;
  18. }

6.函数的嵌套调用和链式访问

6.1嵌套调用

什么是嵌套调用?在函数中调用其他函数的方式被称为嵌套调用。

  1. void hehe()
  2. {
  3. printf("hehe");
  4. }
  5. void three_hehe()
  6. {
  7. hehe();
  8. hehe();
  9. hehe();
  10. }

这里举一个简单的例子。hehe函数的作用是打印 “hehe”,three_hehe函数的作用是打印三个 “hehe” ,函数中一共调用了三次hehe函数。three_hehe中调用了 hehe函数。这样就是嵌套调用了。

6.2链式访问

那什么又是链式访问呢?

将一个函数的返回值作为另一个函数的参数。我们再举一个例子

  1. //strlen:求字符串长度,返回值为字符串中字符个数
  2. //方式1
  3. int main()
  4. {
  5. char a[] = "abcde";
  6. printf("%d", strlen(a));
  7. return 0;
  8. }
  9. //方式2
  10. int main()
  11. {
  12. char a[] = "abcde";
  13. int ret = 0;
  14. ret = strlen(a);
  15. printf("%d", ret);
  16. return 0;
  17. }

两种方式哪种是链式访问呢?答案是方式1。方式1将 strlen函数的运算结果直接作为printf函数的参数。方式2中,我们通过创建中间变量 ret存储strlen函数的返回值,最后打印 ret的值,是一种间接使用 strlen函数返回值的方式。两种方式各有优缺点,方式 1简洁,代码量少,方式 2虽然代码多,但是对于新手来说可读性高。

7.函数递归

前面我们介绍了函数的嵌套调用(在函数中调用其他函数),递归呢,就是函数自己对自己的嵌套调用,自己调用自己。运用递归我们能将大事化小,用少量代码解决复杂问题。但是函数如果不停地调用自己,我们的程序是会崩溃的,所以我们要有一个终止条件,当函数满足该条件时,停止调用自己,并且我们在每一次调用函数后,更接近这个条件

先来看一个简单的递归:如何递归来求 n 的阶乘?

分析:(假设函数名为fac)当 n为1时,函数直接返回1。n大于1时,函数返回 n * fac(n - 1),直到fac(n - 1)中的(n - 1)为1,函数停止递归。

  1. int fac(int n)
  2. {
  3. if (n == 1)
  4. {
  5. return 1;
  6. }
  7. else
  8. {
  9. return (n * fac(n - 1));
  10. }
  11. }
  12. int main()
  13. {
  14. int n = 0;
  15. scanf("%d", &n);
  16. printf("%d", fac(n));
  17. return 0;
  18. }

 假设我们要求5 的阶乘,画图理解。

红色代表的是函数”递“的部分,程序不断的调用fac函数,一层层往下接近终止条件,绿色代表的是函数”归“的部分,当程序遇到终止条件,会 返回函数值,一层层向上地返回函数值,直到递归的起点。 

我们还能用递归求第 n个斐波那契数。(斐波那契数列:1,1,2,3,5,8,13,21,34,55...从第 3项开始每一项都是前两项的和)

可以这样分析,当 n 小于等于 2时,斐波那契数为1,当 n大于 2时,f(n) = f(n - 1)+ f(n - 2)。当 n大于 2我们就进行递归,每次递归调用函数时 n都减一,直到(n - 2) 与 (n -1)这两个表达式满足终止条件,程序结束'递',开始往上'归'。

  1. int Fib(int x)
  2. {
  3. if (x <= 2)
  4. {
  5. return 1;
  6. }
  7. else
  8. {
  9. return Fib(x - 1) + Fib(x - 2);
  10. }
  11. }
  12. int main()
  13. {
  14. int n = 0;
  15. scanf("%d", &n);
  16. printf("%d", Fib(n));
  17. return 0;
  18. }

最后,由于前几天状态不佳,总结这篇博客时相当敷衍,在进行了删改之后重新发布这篇博客。希望以后能及时调整自己,保持一个学习的状态。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/850117
推荐阅读
相关标签
  

闽ICP备14008679号