目录
C语言中引⼊函数(function)的概念,有些翻译为:⼦程序,⼦程序这种翻译更加准确⼀些。 C语⾔中的函数就是⼀个完成某项特定的任务的⼀小段代码。这段代码是有特殊的写法和调用⽅法的。C语⾔的程序其实是由⽆数个⼩的函数组合而成的,也可以说:⼀个⼤的计算任务可以分解成若干个较小的函数(对应较小的任务)完成。同时⼀个函数如果能完成某项特定任务的话,这个函数也是可以复用的,提升了开发软件的效率。
在C语言中函数又分为:
1.库函数
2.自定义函数
比如说sqrt函数
- double sqrt (double x);
- //sqrt 是函数名
- //x 是函数的参数,表⽰调⽤sqrt函数需要传递⼀个double类型的值
- //double 是返回值类型 - 表⽰函数计算的结果是double类型的值
- ret_type fun_name(形式参数)
- {
- }
- //ret_typr 为函数返回类型
- //fun_name 为函数名
- //括号中放的是形式参数
- //{}括起来的是函数体
- #define _CRT_SECURE_NO_WARNINGS 1
- #include
-
- //加法函数
- int Add(int a, int b) {
- return a + b;
- }
-
- int main() {
- int m, n = 0;
- scanf("%d%d", &m, &n);
- int sum=Add(m, n);//调用函数
- printf("%d\n", sum);
- }
上面就是自定义了一个加法函数,需要注意的是函数的参数部分需要交代清楚:参数个数,每个参数的类型是啥,形参的名字叫啥。
1.实际参数就是真实传递给函数的参数。
在上面代码中,传递个函数的m和n就是实际参数,简称实参。
2.而像上述代码中的Add括号中写的a和b称为形式参数,简称形参
形式上存在的,不会向内存申请空间,不会真实存在的,所以叫形式参数。形式参数只有在
- return 9;//可以为数值
- return 3+5;//可以为表达式,先计算表达式,再返回
return ;//返回为空 可用于void类型函数
- int add(){
- return 3.14;//返回为3,自动转换为函数返回类型
- }
- int add(){
- int i =1;
- return 0;//函数彻底返回,后面语句不再执行
- printf("haha")
- }
- int add(int i){
- if(i>0)
- return 0;
- else
- return 1;//每种情况都要返回
- }
- #include
- int main()
- {
- int arr[] = {1,2,3,4,5,6,7,8,9,10};
- int sz = sizeof(arr)/sizeof(arr[0]);
- set_arr(arr, sz);//设置数组内容为-1
- print_arr(arr, sz);//打印数组内容
- return 0;
- }
- void set_arr(int arr[], int sz)
- {
- int i = 0;
- for(i=0; i
- {
- arr[i] = -1;
- }
- }
- void print_arr(int arr[], int sz)
- {
- int i = 0;
- for(i=0; i
- {
- printf("%d ", arr[i]);
- }
- printf("\n");
- }
注意:
•
函数的形式参数要和函数的实参个数匹配
•
函数的实参是数组,形参也是可以写成数组形式的
•
形参如果是⼀维数组,数组⼤⼩可以省略不写
•
形参如果是⼆维数组,⾏可以省略,但是列不能省略
•
数组传参,形参是不会创建新的数组的
•
形参操作的数组和实参的数组是同⼀个数组
五、嵌套调用和链式访问
5.1 嵌套调用
嵌套调用就是函数之间的互相调用。比如说
假设我们计算某年某⽉有多少天?如果要函数实现,可以设计2个函数:
•
is_leap_year():根据年份确定是否是闰年
•
get_days_of_month():调⽤is_leap_year确定是否是闰年后,再根据⽉计算这个⽉的天数
- int is_leap_year(int y)
- {
- if(((y%4==0)&&(y%100!=0))||(y%400==0))
- return 1;
- else
- return 0;
- }
- int get_days_of_month(int y, int m)
- {
- int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- int day = days[m];
- if (is_leap_year(y) && m == 2)
- day += 1;
- return day;
- }
- int main()
- {
- int y = 0;
- int m = 0;
- scanf("%d %d", &y, &m);
- int d = get_days_of_month(y, m);
- printf("%d\n", d);
- return 0;
- }
其中get_days_of_month()函数就是调用了is_leap_year()函数来判断是否是闰年,这就是函数的调用,同理main函数也调用了 scanf()和printf()函数
注意:
函数可以嵌套调用的,但是但是函数是不能嵌套定义的。
5.2 链式访问
所谓链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数,像链条⼀样将函数串起来就是函数 的链式访问。
比如下面的代码
- #include
- int main()
- {
- int len = strlen("abcdef");//1.strlen求⼀个字符串的⻓度
- printf("%d\n", len);//2.打印⻓度
- return 0;
- }
如果把strlen的返回值直接作为printf函数的参数呢?这样就是⼀ 个链式访问的例⼦了
- #include
- int main()
- {
- printf("%d\n", strlen("abcdef"));//链式访问
- return 0;
- }
5.3 printf函数
知道了上面的链式访问,你知道下面代码的输出吗
- #include
- int main()
- {
- printf("%d", printf("%d", printf("%d", 43)));
- return 0;
- }
想要知道输出的结果,我们就要了解一下printf函数的返回值了。通过查询C语言库函数的使用方法。我们知道了printf函数返回值了
printf函数返回的是打印在屏幕上的字符的个数。
上⾯的例⼦中,我们就第⼀个printf打印的是第⼆个printf的返回值,第⼆个printf打印的是第三个
printf的返回值。
第三个printf打印43,在屏幕上打印2个字符,再返回2
第⼆个printf打印2,在屏幕上打印1个字符,再放回1
第⼀个printf打印1
所以屏幕上最终打印:4321
六、函数的声明和定义
6.1 单个文件
⼀般我们在使用函数的时候,直接将函数写出来就使用了。
比如:我们要写⼀个函数判断⼀年是否是闰年。
红色的部分是函数的定义,绿⾊的部分是函数的调⽤。
但是我们把两个部分调转一下:
就会发现报错了,为什么呢?
这是因为C语⾔编译器对源代码进⾏编译的时候,从第⼀行往下扫描的,当遇到is_leap_year
函数调⽤的时候,并没有发现前⾯有is_leap_year的定义,就报出了上述的警告。 怎么把怎么解决这个问题呢?就是函数调⽤之前先声明⼀下is_leap_year这个函数,声明函数只要交代清楚:函数名,函数的返回类型和函数的参数。
这样声明一下就可以了。
函数的调用⼀定要满足,先声明后使用;
函数的定义也是⼀种特殊的声明,所以如果函数定义放在调用之前也是可以的。
6.2 多个文件
⼀般在企业中我们写代码时候,代码可能比较多,不会将所有的代码都放在⼀个⽂件中;我们往往会 根据程序的功能,将代码拆分放在多个⽂件中。然后让不同的人编写。
⼀般情况下,函数的声明、类型的声明放在头⽂件(.h)中,函数的实现是放在源⽂件(.c)⽂件中。
如下:
add.c
- //函数的定义
- int Add(int x, int y)
- {
- return x+y;
- }
add.h
- //函数的声明
- int Add(int x, int y);
test.c
- #include
- #include "add.h"//需要先引用
- int main()
- {
- int a = 10;
- int b = 20;
- int c = Add(a, b);
- printf("%d\n", c);
- return 0;
- }
运行结果:
看以下两个代码:
本篇文章介绍了C语言中函数的基本定义和用法,同时也讲了static和extern关键字的基本用法。希望对你所帮助