一、函数的概念
在编程时,我们会为了实现某个功能编几十行代码,而在我们的项目中可能需要用到很多很多次这个功能。我们每次用到这个功能都把几十遍代码敲一遍是很低效的,所以就需要『函数』。
『函数』是 C 语言的功能单位。某个功能的代码被封装在一个函数里,当我们要实现这个功能的时候,只需要调用函数名就可以使用。在定义函数时,一切工作以功能为目的,根据功能去定函数和返回值。
二、函数的分类
(一)从定义角度分类
- 库函数:C 库实现的
- 自定义函数:程序员自己实现的函数
- 系统函数:操作系统实现的函数
(二)从参数角度分类
- 有参函数
函数有形参,可以是一个或者多个。参数的类型没有要求,取决于函数的功能。
例:
int fun(int a, float b, double c)
{
}
int max(int x, int y)
{
}
- 无参函数
函数没有参数,在形参列表的位置写个(void)或什么都不写
int fun(void)
{
}
int fun()
{
}
(三)从返回值角度分类
- 带返回值的函数
在定义函数时,必须有函数类型;在函数体里,必须有return
如果没有返回值类型,默认返回整型。
char fun() // 定义了一个返回字符数据的函数
{
char b = 'a';
return b;
}
fun()
{
return 1;
}
注:在定义函数的时候,函数的返回值类型到底是什么类型,取决于函数的功能。
- 不带返回值的函数
在定义函数的时候,函数名字前面加void
void fun(形参表)
{
...
...
return; // return 可以不写或者 return 后面接一个分号
}
三、定义函数
函数的定义方法
返回值类型 函数名字(形参列表)
{
// 函数体,函数的功能在函数体实现
}
注意:
- 函数名字是标识符,所以需要满足标识符的命名规则
- 形参可以有,也可以没有,也可以有多个,但是即使是没有,函数名字后面也必须加括号
- 函数体上下位置必须有大括号
- 如果要返回函数的结果,则
return
后边的变量或者值必须与函数名左边的返回值类型一致 - 形参必须带类型,而且以逗号分隔
- 函数的定义不能嵌套
- 所有函数的定义是平行的
(一)定义一个无返回值的函数
#include <stdio.h>
// 无参的
void fun()
{
printf("hello world\n");
printf("-----------\n");
printf("XING9\n");
return ;
}```
// 有参的
void fun1(int a, int b)
{
int sum;
sum = a + b;
printf("%d + %d = %d\n", a, b, sum);
}
int main()
{
fun(); // 调用函数
fun1(98, 70);
return 0;
}
运行结果:
hello world
-----------
XING9
98 + 70 = 168
(二)定义一个有返回值的函数
#include <stdio.h>
// 定义一个有参数的函数
int fun2(int a, int b)
{
int sum;
sum = a + b;
return sum;
}
int main()
{
fun2(98, 70);
return 0;
}
四、函数的声明
(一)声明的概念
对已经定义的函数进行说明。函数的声明可以声明多次。
某些情况下,如果不对函数进行声明,编译器可能不认识这个函数。因为编译器是从上往下编译的。
当被调函数在下、主调函数在上时,需要进行声明。
如果不声明,会怎么样?
int main()
{
myfun1();
return 0;
}
void myfun1()
{
printf("hello world!\n");
printf("xing9\n");
return ;
}
运行结果:
hello world!
xing9
虽然运行出来了,但是会报错
该如何解决呢?
在主函数前加void myfun1();
声明一下即可。
(二)多文件声明
添加一个文件myfun.c
添加一个文件myfun.h
在myfun.c
中实现函数,在myfun.h
中声明函数。
在myfun.c
中,定义函数
# include "myfun.h" // 此时包含的头文件要使用双引号,在当前目录下去找对应头文件
void myfun1()
{
printf("hello world\n");
printf("nihao beijing\n");
return ;
}
在myfun.h
中,声明函数
#ifndef MYFUN_H
#define MYFUN_H
void myfun1();
#endif // MYFUN_H
如果想在main.c
中调用myfun
函数,需添加`#include “myfun.h”
#include <stdio.h>
#include "myfun.h"
int main()
{
myfun1();
return 0;
}
五、函数的调用
根据函数类型的不同,函数调用可分为三种情况:(1)没有参数,没有返回值;(2)有参数,没有返回值;(3)有参数,也有返回值。
#include <stdio.h>
// 声明函数
void myfun1();
void myfun2(int a, int b);
int myfun3(int a, int b);
// 调用函数
int main()
{
// 1.没有参数,没有返回值。
myfun1(); // 直接写函数名
printf("**********\n");
// 2.有参数,没有返回值。
myfun2(34, 21); // 传入常量表达式,也可以传入变量表达式
int x = 10, y = 20;
myfun2(x, y);
printf("**********\n");
// 3.有参数,也有返回值
int c;
c = myfun3(x, 6);
printf("%d\n", c);
printf("sum = %d\n", myfun3(x, 9));
return 0;
}
void myfun1()
{
printf("hello world\n");
printf("Xing Zhenghan\n");
return ;
}
void myfun2(int a, int b)
{
int sum;
sum = a + b;
printf("%d + %d = %d\n", a, b, sum);
}
int myfun3(int a, int b)
{
int sum;
sum = a + b;
return sum;
}
运行结果:
六、总结
(一)注意事项
在定义函数时,关于函数的参数和返回值是什么情况,完全取决于函数的功能。
在编写函数时,一开始不要想着函数如何传参和函数的返回值应该是什么而是当在编写代码的途中,要使用某些值,但是当前函数中不存在,此时就需要进行传参,这时候考虑怎么传参就是合适的时机。
在函数编写完毕后,考虑是否要将某些结果返回给其他函数去使用,此时需要考虑返回值。
(二)使用函数的好处
定义一次,可以多次调用,减少代码冗余度。
代码模块化,方便调试程序。