在之前我很多代码执行都是放在函数里的,这样方便我管理和演示,现在能和大家更好的去了解函数了
考纲教材关于这个的理论知识太多了,且废话占大多数,甚至有些对于小白很晦涩难懂或容易搞混!所以在这我就尽量缩减理论知识,方便大家的理解!!!
一、认识函数
- 函数(function):是就是子程序,是一个大型程序中的实现某特定功能的部分代码,由一个或多个语句块自称。而且相较于其他的代码,具备相对的独立性
- 注(第五版):函数就是功能。每个函数用来实现一个特定的功能。函数的名字应反映其代表的功能
- 函数的分类:库函数、自定义函数。(考纲不着重考,属于补充知识)
二、函数的定义
- 函数是需要先定义,后使用(补:库函数需要调用外部文件在调用)
- 定义函数的要求
- 指定函数的名字
- 指定函数的类型,即函数返回值的类型
- 指定函数的参数的名字和类型,以便在调用是向他们传递数据。无参函数不需要!
- 指定函数应完成什么操作,即指定函数的功能
2.1 函数的定义格式
类型 函数名([形参]){ //不需要参数的函数此处可以不加形参。甚至可以不用加类型
函数体;
[return语句] //如果是无返回值函数可以不需要return
}
- 演示创建一个计算输入的两个数大小的函数,即max函数
#include <stdio.h>
int max(int x,int y) { //定以int返回类型函数max,形参为x,y
if (x > y) { //如果x>y
return x;
}else if (y>x) { //如果y>x
return y;
}else { //相等返回1
return 1;
}
}
main() {
int a, b;
printf("请输入第一个数字:");
scanf("%d",&a);
printf("请输入第二个数字:");
scanf("%d",&b);
printf("最大的数为:%d\n",max(a, b)); //调用max函数,传入实参a,b
}
三、函数的调用
各位道友看到我这么多帖子(没吃过猪肉,也见过猪跑了;我可不是猪哈)基本的调用都明白的大差不差了,所以我在这里提一提理论就行了,我在这只强调一个外部调用自定义函数(考纲不考,只为有兴趣人准备)
- 函数的调用一般为函数名调用:函数名([参数])
- 根据考纲教材所述:调用函数时若函数定义在mian函数之后或不在同一路径,需要在mian函数中或mian函数之前声明。如下3.1
- 但在大部分编译器中是可以不需要声明的,因为在某些情况下可能会对函数调用进行一定程度的推测和延迟解析,即使没有严格按照标准在调用前进行函数声明,也有可能在编译和链接过程中成功找到函数定义而不报错。然而,按照 C 语言标准,为了确保程序的正确性和可移植性,应该在调用一个函数之前对其进行声明,如果函数定义在调用之后。
3.1 调用外部xxxx.c中定义的自定义函数和main函数之后自定义函数(Visual Studio编译器)
- 源文件function.c代码
#include <stdio.h>
int min(int,int); //函数声明(也称为函数原型)
/*
告知编译器有一个名为min的函数,它接受两个int类型的参数并返回一个int类型的值。
这样当在function.c的main函数中调用min函数时,编译器在编译function.c时就知
道这个函数的存在、参数类型和返回值类型,从而能够正确地进行编译,而不会因为找
不到函数定义而报错。
*/
int max(int x,int y) { //定以int返回类型函数max,形参为x,y
if (x > y) { //如果x>y
return x;
}else if (y>x) { //如果y>x
return y;
}else { //相等返回1
return 1;
}
}
main() {
int a, b;
int add(int,int); //只要是在调用之前声明位置可以任意(但要合规)
printf("请输入第一个数字:");
scanf("%d",&a);
printf("请输入第二个数字:");
scanf("%d",&b);
printf("最大的数为:%d\n",max(a, b)); //调用max函数,传入实参a,b
printf("最小的数为:%d\n",min(a,b));
printf("两个数相加的结果为:%d",add(a,b)); //调用add函数
}
int add(int x,int y){
int a=x+y;
return a;
}
- 外部文件minTest.c代码
int min(int x,int y) {
if (x < y) {
return x;
}else if (y<x) {
return y;
}else {
return 1;
}
}
- 如下是没有声明的运行结果
- 函数的声明有以下两种格式
函数类型 函数名(类型1 参数名,类型2 参数名,.....); //函数的首部称为函数原型
函数类型 函数名(类型1,类型2,类型3,.......); //所以使用函数原型做声明
四、认识实参与形参
在上文中,本帅哥也提到了什么是实参与形参,但是在这我将详细讲解
4.1 实参
- 定义:在函数调用时传递给函数的具体值或变量。
- 作用:
- 实参将具体的数据传递给函数,使得函数能够根据这些数据进行操作。实参可以是常量、变量、表达式等。
- 实参的值会被复制(对于值传递方式)或其地址会被传递(对于指针传递方式)给相应的形参,以便函数内部可以使用这些数据。
4.2 形参
- 定义:形参是在函数定义中声明的参数变量,出现在函数名后的括号内。它们仅在函数被调用时才被分配内存空间,用于接收来自调用者传递过来的值。
- 作用:
- 形参作为函数内部的局部变量,用于接收外部传递的值,并在函数内部参与运算和处理。
- 函数通过形参与外部进行数据交互,实现特定的功能。
4.3 实参与形参的关系
-
数据传递:
- 当函数被调用时,实参的值被传递给形参。这个过程可以是值传递(将实参的值复制给形参)或引用传递(将实参的地址传递给形参,通过指针操作可以修改实参的值)。
- 例如,在值传递中,修改形参的值不会影响实参的值;而在引用传递中,修改形参(实际上是通过指针修改实参所指向的内存区域)可以影响实参的值。
-
类型匹配:
- 实参的类型必须与对应的形参类型相匹配,或者能够进行自动类型转换。否则,会导致编译错误。
-
数量一致:
- 实参的数量必须与形参的数量一致。如果实参数量多于形参数量,多余的实参将被忽略;如果实参数量少于形参数量,未被初始化的形参将具有未定义的值。
4.4 补充(当定义的函数不知道需要的形参个数时)
这个会在后续具体讲到,关于宏
1、使用va_list
、va_start
、va_arg
和va_end
宏来实现可变参数函数。
#include <stdio.h>
#include <stdarg.h>
int sum(int numArgs,...) {
va_list args;
int sum = 0;
int arg;
va_start(args, numArgs);
for (int i = 0; i < numArgs; i++) {
arg = va_arg(args, int);
sum += arg;
}
va_end(args);
return sum;
}
int main() {
int result = sum(3, 10, 20, 30);
printf("Sum: %d\n", result);
return 0;
}
2、使用预处理器宏来模拟可变参数函数。
#include <stdio.h>
#define SUM(...) sum(__VA_ARGS__, 0)
int sum(int num,...) {
int result = num;
va_list args;
va_start(args, num);
int arg;
while ((arg = va_arg(args, int))!= 0) {
result += arg;
}
va_end(args);
return result;
}
int main() {
int result = SUM(10, 20, 30);
printf("Sum: %d\n", result);
return 0;
}
五、函数的递归
- 函数递归:简而言之就是自己调用自己!!!!!
- 明白这个,我用用此题帮助大家理解:等差数列,输入第一个数,公差为2,求第18项为多少,只能用函数的递归!!!!(第五版p182题目改编,更易懂!!)
#include <stdio.h>
main(){
int grade;
printf("请输入第一项数的值:");
scanf("%d",&grade);
int c=Function_grade(grade,18); //调用递归函数求等差数列项函数
printf("第18项结果为:%d", c);
}
int Function_grade(int x,int y) {
int c;
if (y == 1) {
return x;
}
else {
c= Function_grade(x, y - 1)+2;
}
return c;
}
理解: 当y不满足1时是不是一致在调用其本身,所以我们可以直接看y=1时结果为x,然后y减到1需要减17此,加上最后这一次不用减故为18此,所以当我们知道了递归次数和每次减时加2,我们就能知道最终值了!(懵的套数学等差公式看看我这个解释算出来的结果对不对)
本7.0就先讲这么多后面还有关于局部变量全局遍历,生命周期等知识在7.1讲解!感谢大家的支持