第7章 函数 教学PPT_190830ppt课件.pptx
《第7章 函数 教学PPT_190830ppt课件.pptx》由会员分享,可在线阅读,更多相关《第7章 函数 教学PPT_190830ppt课件.pptx(124页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第7章 函数 教学PPT_190830 第第7章章 函数函数递归函数 内联函数 变量作用域 函数概念与定义 函数三要素 函数的参数传递多文件之间的变量引用与函数调用 函数与指针 C语言常用的标准库 7.1 函数的概念假设有一个游戏程序,程序在运行过程中,要多次发射炮弹、转向、战绩统计等,如果发射炮弹的动作需要编写100行的代码,在每次实现发射炮弹的地方都重复地编写这100行代码,程序会变得很“臃肿”,可读性也非常差。 为了解决代码重复编写的问题,这时候就要考虑模块化设计,可以将发射炮弹的代码提取出来放在一个中,并为这段代码起个名字,这样每次发射炮弹时只需通过这个名字调用发射炮弹的代码即可。提取
2、出来用于实现某项特定功能的代码可以看作是程序中定义的一个函数。7.1 函数的概念 在C语言中,函数是最简单的程序模块。函数被视为程序设计的基本逻辑单位,一个C程序是由一个main()函数和若干个其他函数组成的。程序执行从main()函数开始,由main()函数调用其他函数实现相应功能,直到程序结束。7.1 函数的概念 函 数库函数自定义函数7.1 函数的概念 库函数可以直接被调用,例如之前使用过的printf()函数、scanf()函数。自定义函数是用户自己定义的具有特定功能的函数。7.1 函数的概念 在C语言中,定义和调用函数时,要注意以下几个问题:(1)C程序的执行是从main()函数开始
3、的。(2) 一个C程序由一个或多个程序模块组成,每一个程序模块都是一个源程序文件。一个源程序文件由一个或多个函数以及其他有关内容(如指令、数据声明与定义等)组成。(3) 所有函数都是平行的,即函数定义是分别进行的,是互相独立的。一个函数并不从属于另一个函数,即函数不能嵌套定义。7.1 函数的概念 7.2 函数的定义返回值类型 函数名(参数类型 参数名1,参数类型 参数名2,参数类型 参数n) 执行语句 return 返回值; 返回值类型:用于限定函数返回值的数据类型,当返回值类型为void时,return语句可以省略; 函数名:表示函数的名称; 参数类型:用于限定调用函数时传入函数中的数据类型
4、; 参数:用于接收传入函数中的数据; return关键字:用于结束函数,将函数的返回值返回到函数调用处; 返回值:被return语句返回的值。7.2 函数的定义 int add(int a, int b)int sum;sum = a + b;return sum;7.2 函数的定义add()函数的返回值类型为int,有两个int类型的参数a与b。在函数体内,首先定义了一个int类型的变量sum,然后将参数a与b相加的结果赋值给sum,最后使用return关键字将sum返回。当有调用者调用add()函数时,传入相应的参数值,就会得到相应的求和结果。 7.2 函数的定义函数不能嵌套定义:int
5、add(int a, int b) /定义add()函数int sum;sum = a + b;return sum;char sub(int x, int y) /错误int sum = x - y;return sum; 7.2 函数的定义函数的“定义”与“声明”并不是一个意思,“定义”是指对函数功能的确立,函数的定义是一个完整的、独立的函数单位。函数的声明则是把函数名、参数列表、返回值类型通知编译系统,以便在调用时系统按照此声明进行对照检查。通俗的说法,函数定义有函数体,函数声明没有函数体。 7.2 函数的定义在C语言中,函数声明有两种形式,具体如下:返回值类型 函数名(参数类型1 参数
6、名1,参数类型2 参数名2,参数类型n 参数名n);返回值类型 函数名(参数类型1,参数类型2,参数类型n);int add(int a,int b);int add(int, int); 7.3 函数三要素函数三要素:函数名参数列表返回值类型 7.3.1 函数名在C语言中,函数名不仅仅是一个标识符,它还是一个指针常量,记录了函数代码在内存中的地址。函数代码存储在内存代码区,函数代码的起始地址就是函数的入口地址,这个入口地址就保存在函数名当中。当有调用者调用函数时,函数名负责告诉调用者函数的入口地址,实现函数地调用。 7.3.1 函数名输出函数名就是输出函数的入口地址。int add(int
7、a, int b)/printf(%pn, add); /输出add()函数代码的存储地址 7.3.1 函数名函数名是记录函数入口地址的指针常量,有些操作对函数名是非法的、不合理的,例如,给函数名赋值、比较两个函数名大小、使用sizeof运算符计算函数大小等。 在书面用语中,函数名后面的小括号不能丢失,例如,add()函数,不能写作add函数。小小提示提示:内存地址打印内存地址打印 7.3.2 参数列表1、无参函数参数列表为空的函数被称为无参函数。 void func() /定义一个无参函数 printf(这是我的第一个函数!n);7.3.2 参数列表 上述定义的func()函数就是一个无参函
8、数,在定义时参数列表为空。要想执行这个函数,需要在main()函数中调用它。int main() /在main()函数中调用func()函数 func(); return 0;7.3.2 参数列表 定义无参函数时,即便函数参数列表为空,函数名后面的小括号也不能省略。小括号是函数的标识,没有小括号,编译器会报错。7.3.2 参数列表 void func/错误,func后面缺少()printf(这是一个无参函数!n);7.3.2 参数列表 2、有参函数与无参函数相比,有参函数需要在定义时,在函数名称后面的括号中填写参数。所谓的参数是一个形式变量,用于接收调用函数传入的数据。7.3.2 参数列表 v
9、oid func(int x, int y) /定义有参数函数int sum;sum= x+y;printf(x+y=%dn, sum);7.3.2 参数列表 上述定义的func()函数是一个有参函数,可以在main()函数中调用该函数。int main()func(3,5); /调用func()函数return 0;7.3.2 参数列表 形参和实参之间的数据传递是单向的,即只能由实参传递给形参,不能由形参传递给实参。7.3.2 参数列表 函数的返回值是指函数被调用之后,返回给调用者的值。函数返回值的具体语法格式如下: return 表达式;返回值7.3.3 返回值类型 return后面表达式
10、的类型和函数定义返回值的类型应保持一致。如果不一致,就有可能会报错。如果函数没有返回值,可以直接在return语句后面加分号或省略return语句。需要注意的是,如果函数没有返回值,函数返回值类型要定义为void。7.3.3 返回值类型 return语句将函数调用结果返回给调用者,函数调用就结束了,因此return语句的深层含义就是结束函数的执行。在函数体内,无论代码实现多么复杂,只要函数在执行时遇到return语句,函数执行就会立即结束,return语句后面的代码不会再执行。7.3.3 返回值类型 #define _CRT_SECURE_NO_WARNINGS#include int com
11、pare(int x, int y)/定义compare()函数if (x y)return x;/调用return语句else if (x y)return y;/调用return语句elsereturn 0;/调用return语句7.3.3 返回值类型int main()int a, b,ret;printf(请输入两个整数:);scanf(%d%d, &a, &b);ret = compare(a, b);printf(%dn, ret);return 0; 7.4.1 函数调用过程程序在编译或运行时调用某个函数以实现某种功能的过程称为函数调用。在C语言程序中,遇到一个函数调用,系统就会
12、跳转到函数内部执行这个函数,执行完毕后再跳转回来接着执行下一条指令。系统在函数调用之前可以保护好当前程序的执行“现场”,去执行函数,函数执行完毕后,再恢复当前程序的执行“现场”,这个过程类似于视频软件中的暂停与播放。 7.4.1 函数调用过程int func(int x, int y)return x+y; 7.4.1 函数调用过程func()函数代码存储在代码区,编译器根据函数名找到函数入口地址,读取函数代码,根据函数代码在栈上分配相应的内存空间,将函数中的变量、数据、指令等存储在相应的内存区域中。 7.4.1 函数调用过程例如func()函数中的形参x和y,编译器会在栈上为x与y分配相应的
13、内存空间,这时x和y由形参变量变成了真正的变量。调用者传入的具体的数据“3”和“5”分别被存储到x和y标识的内存块中,即在函数调用时,形参获取实参的数据(相当于发生了赋值),该数据在本次函数调用中有效,一旦调用的函数执行完毕,形参的值占用的内存空间就会自动释放。 7.4.1 函数调用过程如果函数中有其他数据、指令等,编译器也会根据上下文环境为其分配适当的内存空间完成计算。函数所有代码执行完毕之后,编译器会收回为函数代码分配的空间,并清理现场,将函数返回结果通过指定的寄存器返回给调用者,调用者获取结果之后继续执行程序。 7.4.2 函数调用方式主函数可以调用其他普通函数,普通函数可以互相调用,但
14、是不能调用主函数。函数调用格式如下:函数名(实参1,实参2,实参n);当调用一个函数时,需要明确函数名和实参列表。参数列表中的实参可以是常量、变量、表达式或者为空,多个参数之间使用英文逗号分割。 如果调用的是无参函数,实参列表可以空,但是不能省略括号。在调用函数时,要求实参与形参必须满足三个条件:个数相等、顺序对应、类型匹配。7.4.2 函数调用方式 1、将函数作为表达式调用将函数作为表达式调用时,函数的返回值参与表达式的运算,此时要求函数必须有返回值。int a=max(10,20); /将函数作为表达式调用7.4.2 函数调用方式 2、将函数作为语句调用函数以语句的形式出现时,可以将函数作
15、为一条语句进行调用。printf(“hello world!n”); /将函数作为语句调用3、将函数作为实参调用将函数作为实参调用时,其实就是将函数返回值作为函数参数,此时要求函数必须有返回值。printf(“%dn”,max(10,20); /将函数作为实参调用7.4.2 函数调用方式 C语言中函数的定义是独立的,即一个函数不能定义在另一个函数内部。但在调用函数时,可以在一个函数中调用另一个函数,这就是函数的嵌套调用。7.4.2 函数调用方式 7.4.2 函数调用方式#include void printArr(int arr) int i;for (i = 0; i 10; i+) pri
16、ntf(%3d, arri);void initArr() int arr10, i;for (i = 0; i 10; i+)arri = i;printArr(arr); 当在main()函数中调用initArr()函数时,函数嵌套调用过程如右图。7.4.2 函数调用方式 程序执行main()函数开头部分,遇到函数调用语句,调用initArr()函数,流程转向initArr()函数入口。在initArr()函数体中遇到printArr()函数的调用,流程转向printArr ()函数入口。 printArr()函数调用完毕回到initArr()函数调用点。 initArr()函数调用完毕,
17、跳转至main()函数部分。继续执行main()函数的剩余部分,直到程序执行结束。7.4.2 函数调用方式 函数的形参如果是一个普通变量,实际参数到形式参数的数据传递过程就叫作值传递。值传递是将实际参数复制一份副本传递到函数中,在函数内部对参数进行修改,而不会影响到实际参数。7.5.1 值传递 #include void func(int a,int b ) int temp;temp = a;a = b;b = temp;printf(a=%d b=%dn, a, b);7.5.1 值传递int main() int x = 10, y = 20; /定义实际参数 func(x, y); /
18、调用func()函数 /输出main()函数的实际参数变量 printf(x=%d y=%dn, x, y); return 0; 7.5.1 值传递在上述代码中,调用func()函数时,编译器会在栈中为参数a、b分别分配一块内存空间,然后用变量x和y的值初始化变量a和b,在func()函数内部交换a、b的值,变量x、y的值并不受影响。 7.5.2 址传递地址传递的是变量的地址,函数形式参数与实际参数指向同一块内存地址,即都指向实际参数所在的内存空间。在函数中通过地址修改变量的值,就是修改实际参数的值。址传递 7.5.2 址传递#include void func(int* a,int* b
19、) int temp; temp = *a; *a = *b; *b = temp; printf(*a=%d *b=%dn, *a, *b);int main() int x = 10, y = 20; func(&x, &y); printf(x=%d y=%dn, x, y); return 0; 7.5.2 址传递上述代码的址传递过程如下图。 7.5.3 const修饰参数有时在定义函数时,在函数内部,只想让参数参与某种运算,不想改变参数的值,这时可以使用const关键字修饰形式参数。void func(const int num ) num += 10; /错误 if (num %
20、2 = 0) printf(%d是偶数!,num); else printf(%d是奇数!,num); 7.5.3 const修饰参数num被const关键字修饰,是不可更改的。但是const修饰的变量,虽然无法通过变量本身修改其值,却可以通过指针进行修改,定义一个指向num的指针,通过指针可以修改num的值。int* p = #/定义指向num的指针*p += 10;/通过指针改变num的值 7.5.4 可变参数函数可变参数函数顾名思义是参数可变的函数,参数可变是指参数的数量可变。前面章节使用过的可变参数函数,最经典的就是printf()函数与scanf()函数,它们可以根据用户的需
21、要传入数量不等的参数。 7.5.4 可变参数函数除了库函数,C语言还允许用户自定义可变参数函数。定义可变参数函数时,第一个参数是固定强制的int类型,用于指定参数个数;定义好固定参数之后,再定义可选参数,可选参数使用三个点号()表示。定义可变参数需要包含stdarg.h标准库文件,该标准库定义了实现可变参数函数需要的变量和宏。 7.5.4 可变参数函数(1)在程序顶部包含stdarg.h标准库文件。(2)定义函数,指定固定的参数,最后一个参数用省略号表示。(3)在函数中定义一个va_list类型变量,该类型在stdarg.h中定义。(4)使用int类型参数(参数个数)和宏va_start初始化
22、va_list变量,使其成为一个参数列表。宏va_start在stdarg.h标准库文件中定义。(5)使用宏va_arg和va_list变量访问参数列表中的每一项。(6)使用宏va_end清理赋予va_list变量的内存。 7.5.4 可变参数函数#include #include void func(int n, .) va_list valist; va_start(valist, n); for (int i = 0; i n; i+) printf(%d , va_arg(valist, int); va_end(valist);int main()func(1,1); printf(
23、n);func(2, 6, 9); printf(n);func(3, 100, 24, 88);printf(n);return 0; 7.5.4 可变参数函数调用可变参数函数时,传入的参数会存储在可变参数列表中,函数从参数列表中获取每一个参数参与运算,该参数列表实质上就是一个动态数组,在使用完毕后,需要使用宏va_end进行释放,否则会造成内存泄露。 多学一招:带参数的多学一招:带参数的main()main()函数函数main()函数是带参函数,其完整声明有如下两种形式:int main( int argc, char *argv );或int main(int argc, char *a
24、rgv); 多学一招:带参数的多学一招:带参数的main()main()函数函数main()函数有两个参数,argc参数表示在命令行中输入的参数个数,argv参数是字符串指针数组,其各元素值为命令行中各字符串的首地址。数组第一个元素指向当前运行程序文件名的字符串。指针数组的长度即为参数个数,数组元素初值由系统自动赋予。 7.6 递归函数函数也可以调用本身,函数直接或者间接调用函数本身,这样的函数称为递归函数。 7.6.1 递归函数的概念一种计算过程,如果其中每一步都要用到前一步或前几步的结果,这个计算就是可递归的。用递归过程定义的函数,称为递归函数。在数学运算中,经常会遇到计算多个连续自然数之
25、间的和的情况。递归例如,要计算1n之间自然数之和,就需要先计算1加2的结果,用这个结果加3再得到一个结果,用新得到的结果加4,以此类推,直到用1(n-1)之间所有数的和加n,就得到了1n之间的自然数之和。 int getsum(int n)int sum=0;sum = getsum(n - 1); /调用函数本身return sum + n; /返回sum+n结果,即getsum(n-1)+n结果7.6.1 递归函数的概念 递归过程如下:main() getsum(); getsum() getsum(); 7.6.1 递归函数的概念 在main()函数中调用,系统却抛出“栈溢出”异常,仔细
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第7章 函数 教学PPT_190830ppt课件 教学 PPT_190830ppt 课件
限制150内