文章目录
- 1. 函数的介绍
- 2. 函数的分类
- 2.1 库函数
- 2.2 自定义函数
- 3. 函数的参数
- 4. 函数的调用
- 4.1 传值调用
- 4.2 传址调用
1. 函数的介绍
1. 什么是函数?
- 函数是完成特定任务的独立程序代码单元。语法规则定义了函数的结构和使用方式。
- 一些函数执行某些动作,如 printf ( ) 把数据打印到屏幕上;
- 一些函数找出一个值供程序使用,如 strlen( ) 把指定字符串的长度返回给程序。
- 一般而言,函数可以同时具备以上两种功能。
2. 为什么要使用函数?
- 使用函数可以省去编写重复代码的苦差。如果程序要求多次完成某项任务,那么只需要编写一个合适的函数,就可以在需要时使用这个函数,或者在不同的程序中使用该函数,就像许多程序中使用 putchar( ) 一样。
- 提高程序代码的可读性,即使程序只完成某项任务一次,也值得使用函数。因为函数让程序更加模块化,从而提高程序代码的可读性,更方便后期修改、完善。
- 有了这些函数,我们就不用去关注内部的实现细节,只需要将注意力放在程序的实现逻辑上即可。
2. 函数的分类
2.1 库函数
1. 什么是库函数?
- C 语言内置的函数称之为库函数。
- 如:printf、strlen、time、rand …等。
2. C 语言常用库函数
- IO函数
- 字符串操作函数
- 字符操作函数
- 内存操作函数
- 时间/日期函数
- 数学函数
- 其他库函数
3. 如何学习库函数?
- C 语言中的库函数有很多种,倒也不必全部记住,只要掌握查询库函数的技能就行了。
- 个人在使用的查询库函数的网址:https://cplusplus.com。
- 因为本人英语基础比较差,所以才逼着自己看这种全英文的网站,中文网站在后面会分享。
- 注:使用库函数,必须包含 #include 对应的头文件。
4. 库函数查询工具
- MSDN(Microsoft Developer Network)
- http://www.cplusplus.com
- https://en.cppreference.com(英文版)
- https://zh.cppreference.com(中文版)
2.2 自定义函数
1. 函数的组成
ret_type fun_name(para1, * )
{
statement;//函数体
}
- ret_type:返回类型,返回类型有 Int、float、double、void 等,具体看函数内的返回类型决定该用什么。
- fun_name:函数名,函数名随意,但是取得名字要有意义。
- para1:函数参数,参数可以有零个或多个。
2. 什么是自定义函数?
- 作为一门高级编程语言,C 语言还允许我们自己进行函数的封装。
- 当我们将代码段根据其功能封装成为一个个不同的函数时,其实就是模块化程序设计,也就是把大的计算任务拆分成若干个较小的任务来实现。
- 下面通过一个例子来讲解一下函数的封装。下面代码封装一个 print_C 函数,调用它就可以打印一个由井字符(#) 构成的字母 C。
#include <stdio.h>
void print_C(void); //函数声明
void print_C(void) //函数定义开始
{
printf(" ###### \n");
printf("## ##\n");
printf("## \n");
printf("## \n");
printf("## \n");
printf("## ##\n");
printf(" ###### \n");
}//函数定义结束
int main()
{
print_C();//调用 print_C 函数
return 0;
}
3. 为什么要自定义函数?
因为随着程序规模的变大,都免不了会遇到下面这些问题:
- main 函数变得相当冗杂,程序可读性差。
- 程序复杂度不断提高,编程变成了头脑风暴。
- 代码前后关联度高,修改代码往往牵一发而动全身。
- 变量的命名成了问题,一个项目中那么多的变量,哪来那么多名字给你用。
- 为了在程序中多次实现某功能,不得不重复多次写相同的代码。
- ……
3. 函数的参数
- 函数的参数分为形参和实参。
1. 形式参数(形参)
- 形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。
- 形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有效。
- 对形参的修改不能改变实参。
2. 实际参数(实参)
- 在真正调用这个函数的时候,传递进去的数值就叫做实参。
- 实参可以是:常量、变量、表达式、函数等。
- 无论实参是何种类型的量,在进行函数调用时,实参必须有确定的值,以便把这些值传送给形参。
3. 函数参数实例
- 编写一段函数用来求四个数中得最大值。
#include <stdio.h>
//形参 q w e r 是用来接收实参传过来的值
int get_max(int q, int w, int e, int r)
{
int x = q > w ? q : w;
int y = e > r ? e : r;
return x > y ? x : y;//返回四个数中得最大值
}
int main()
{
int a, b, c, d;
scanf("%d %d %d %d", &a, &b, &c, &d);
int max = get_max(a, b, c, d);
//a b c d 就是传递给函数的有实际意义的值,所以叫实参
printf("max = %d\n", max);
}
4. 函数参数总结
- 形参和实参的功能说白了就是用作数据传送。
- 当发生函数调用时,实参的值会传递给形参,并且这种传输具有单向性(也就是不能把形参的值传回给实参)。
- 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只在函数内部有效,不能在函数外部使用。
4. 函数的调用
写一个函数用以交换两个变量的值
4.1 传值调用
#include <stdio.h>
void swap(int x, int y)
{
int z = x;
x = y;
y = z;
}
int main()
{
int a, b;
scanf("%d %d", &a, &b);
printf("交换前:a = %d,b = %d\n", a, b);
swap(a , b);
printf("交换后:a = %d,b = %d\n", a, b);
return 0;
}
- 可以看到,和我们预想的结果完全不一样,明明把参数传进去了,可为啥没有任何变化呢?
- 因为函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
- 函数内部创建的形参和外部的实参之间一点关系都没有, 这时候就要用到俺们的传址调用了。
4.2 传址调用
- 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
- 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
作函数外部的变量。
#include <stdio.h>
//用指针变量 x y来接收传来的地址,让形参和实参之间产生点关系
void swap(int* x, int* y)//交换地址所指向的那个值
{
int z;
//在指针中,*指针变量名 等价于 指针指向的那个变量,所以这段代码的实际意义应该是
z = *x; //z = a;
*x = *y; //a = b;
*y = z; //b = z;
}
int main()
{
int a, b;
scanf("%d %d", &a, &b);
printf("交换前:a = %d,b = %d\n", a, b);
swap(&a , &b);//将 a b 的地址传给函数
printf("交换后:a = %d,b = %d\n", a, b);
return 0;
}
函数下半部分传送门:https://editor.csdn.net/md/?not_checkout=1&spm=1001.2014.3001.4503