C语言程序设计:第7章 函数

上传人:公**** 文档编号:570221756 上传时间:2024-08-02 格式:PPT 页数:52 大小:1.20MB
返回 下载 相关 举报
C语言程序设计:第7章 函数_第1页
第1页 / 共52页
C语言程序设计:第7章 函数_第2页
第2页 / 共52页
C语言程序设计:第7章 函数_第3页
第3页 / 共52页
C语言程序设计:第7章 函数_第4页
第4页 / 共52页
C语言程序设计:第7章 函数_第5页
第5页 / 共52页
点击查看更多>>
资源描述

《C语言程序设计:第7章 函数》由会员分享,可在线阅读,更多相关《C语言程序设计:第7章 函数(52页珍藏版)》请在金锄头文库上搜索。

1、1第7章函数 7.1 7.1 函数的基本概念函数的基本概念 7.2 7.2 函数的基本应用函数的基本应用 7.3 7.3 数组作为函数参数数组作为函数参数 7.4 7.4 函数的嵌套调用函数的嵌套调用 7.5 7.5 函数的递归调用函数的递归调用 7.6 7.6 局部变量与全局变量局部变量与全局变量 7.7 7.7 变量的存储方式变量的存储方式 7.8 7.8 内部函数与外部函数内部函数与外部函数 7.9 7.9 编译预处理编译预处理7.1 7.1 7.1 7.1 函数的基本概念函数的基本概念函数的基本概念函数的基本概念 程序设计中的程序设计中的“函数函数”是从英文是从英文“functionf

2、unction”翻译过来的,翻译过来的,从其意义上来说,函数带有功能的含义,也就是说程序中定义从其意义上来说,函数带有功能的含义,也就是说程序中定义一个函数的目的是让它完成一定的功能,并且这个功能在程序一个函数的目的是让它完成一定的功能,并且这个功能在程序中会多次被使用。通常对一个复杂问题进行程序设计时,会采中会多次被使用。通常对一个复杂问题进行程序设计时,会采用分解法把问题分解为多个相对独立的子问题,每个子问题对用分解法把问题分解为多个相对独立的子问题,每个子问题对应程序的一个功能模块。应程序的一个功能模块。 从用户使用的角度来看,函数分为从用户使用的角度来看,函数分为“库函数库函数”和和“

3、自定义自定义函数函数”两种。由系统提供给用户直接调用的函数称为库函数;两种。由系统提供给用户直接调用的函数称为库函数;用户在程序中自行定义并调用的函数称为自定义函数。用户在程序中自行定义并调用的函数称为自定义函数。7.1 7.1 7.1 7.1 函数的基本概念函数的基本概念函数的基本概念函数的基本概念 程序设计中的程序设计中的“函数函数”是从英文是从英文“functionfunction”翻译过来的,翻译过来的,从其意义上来说,函数带有功能的含义,也就是说程序中定义从其意义上来说,函数带有功能的含义,也就是说程序中定义一个函数的目的是让它完成一定的功能,并且这个功能在程序一个函数的目的是让它完

4、成一定的功能,并且这个功能在程序中会多次被使用。通常对一个复杂问题进行程序设计时,会采中会多次被使用。通常对一个复杂问题进行程序设计时,会采用分解法把问题分解为多个相对独立的子问题,每个子问题对用分解法把问题分解为多个相对独立的子问题,每个子问题对应程序的一个功能模块。应程序的一个功能模块。 从用户使用的角度来看,函数分为从用户使用的角度来看,函数分为“库函数库函数”和和“自定义自定义函数函数”两种。由系统提供给用户直接调用的函数称为库函数;两种。由系统提供给用户直接调用的函数称为库函数;用户在程序中自行定义并调用的函数称为自定义函数。用户在程序中自行定义并调用的函数称为自定义函数。库函数库函

5、数库函数库函数信息学院计算机系陈湘骥6/25在在C C语言中,提供的标准库函数,例如语言中,提供的标准库函数,例如printfprintf、scanfscanf、fabsfabs、strlwrstrlwr等等等等特点是使用方便,只需要在程序开头使用特点是使用方便,只需要在程序开头使用# #includeinclude引引用相应的用相应的. .h h文件,例如文件,例如#include #include 、#include #include 等等除了使用库函数,还可以自己定义函数除了使用库函数,还可以自己定义函数自定义函数自定义函数自定义函数自定义函数函数定义的一般形式:函数定义的一般形式:类型

6、说明符类型说明符 函数名函数名( (形式参数声明列表形式参数声明列表) ) 说明与定义部分说明与定义部分; ; 语句部分语句部分; ; 当形参有多个时,每个参数必须独立说明,并用逗号分隔。例如:当形参有多个时,每个参数必须独立说明,并用逗号分隔。例如:int max(int max(intint a, a, intint b) b) . . . . 如果函数不需要参数,形参表可以为空,但是不能省略函数名后面的括号。如果函数不需要参数,形参表可以为空,但是不能省略函数名后面的括号。例如:例如:void info()void info() . . . . voidvoid表示函数无返回值,不需要将

7、函数的处理结果以函数返回值的方式传回表示函数无返回值,不需要将函数的处理结果以函数返回值的方式传回给函数调用者给函数调用者7.2 7.2 7.2 7.2 函数的调用函数的调用函数的调用函数的调用函数调用主要有两种方式:函数调用表达式和函数调用语句函数调用主要有两种方式:函数调用表达式和函数调用语句1.1.函数作为表达式的一部分,例如函数作为表达式的一部分,例如 big = max(10, 100); / big = max(10, 100); /作为赋值表达式的一部分作为赋值表达式的一部分 printf(%dn, max(10, 100); / printf(%dn, max(10, 100)

8、; /作为作为printfprintf函数的实际参数函数的实际参数 sum = max(x, y) + 200; / sum = max(x, y) + 200; /作为算术表达式的一部分作为算术表达式的一部分2.2.函数调用语句,例如函数调用语句,例如 printf(Welcome to Cn);printf(Welcome to Cn); 函数调用构成一条单独的语句函数调用构成一条单独的语句程序执行到一个函数调用另一个函数的语句时,程序的执行流程从发生函数程序执行到一个函数调用另一个函数的语句时,程序的执行流程从发生函数调用的位置离开主调函数,转移到被调函数开始执行。被调函数中执行到调用的

9、位置离开主调函数,转移到被调函数开始执行。被调函数中执行到returnreturn语句或执行完最后一条语句时,程序执行流程重新回到主调函数的离语句或执行完最后一条语句时,程序执行流程重新回到主调函数的离开位置,继续执行主调函数后面的语句或表达式。开位置,继续执行主调函数后面的语句或表达式。例例7-17-1示例程序如下:示例程序如下: 1 1 #include #include 2 int max(int a, int b) 2 int max(int a, int b) 3 3 4 int result; 4 int result; 5 if(a b) 5 if(a b) 6 result =

10、 a; 6 result = a; 7 else 7 else 8 result = b; 8 result = b; 9 return result; 9 return result; 10 10 11 int main() 11 int main() 12 12 13 int i = 10; 13 int i = 10; 14 int j = 100; 14 int j = 100; 15 int x = max(i, j); 15 int x = max(i, j); 16 printf(x=%dn, x); 16 printf(x=%dn, x); 17 return 0; 17 re

11、turn 0; 18 18 例例7-27-2:编写程序,使用函数实现根据输入的考试成绩输出对应:编写程序,使用函数实现根据输入的考试成绩输出对应的成绩等级。的成绩等级。 1 #include 1 #include 2 2 voidvoid outputLevel(double score) outputLevel(double score) 3 3 4 if(score = 90) 4 if(score = 90) 5 printf(Level An); 5 printf(Level An); 6 else if(score =80) 6 else if(score =80) 7 printf

12、(Level Bn); 7 printf(Level Bn); 8 else if(score =70) 8 else if(score =70) 9 printf(Level Cn); 9 printf(Level Cn); 10 else if(score =60) 10 else if(score =60) 11 printf(Level Dn);11 printf(Level Dn); 12 else 12 else 13 printf(Level En); 13 printf(Level En); 14 14 return; /return; /可以省略可以省略 15 15 16 i

13、nt main() 16 int main() 17 17 18 double sc; 18 double sc; 19 scanf(%lf, &sc); 19 scanf(%lf, &sc); 20 20 outputLevel(sc);outputLevel(sc); 21 return 0; 21 return 0; 22 22 函数参数的值传递函数参数的值传递函数参数的值传递函数参数的值传递 调用定义了形参的函数时需要把实参的值传递给形参,前调用定义了形参的函数时需要把实参的值传递给形参,前面说过,实参必须与函数定义中的形参在次序和数量上匹配,面说过,实参必须与函数定义中的形参在次序和

14、数量上匹配,在数据类型上兼容。在数据类型上兼容。 C C语言同时规定,实参向形参的传递数据是单向值传递。语言同时规定,实参向形参的传递数据是单向值传递。例例7-37-3:使用函数实现交换两个整数的值。:使用函数实现交换两个整数的值。1 #include 1 #include 2 void swap(int a, int b)2 void swap(int a, int b)3 3 4 int temp;4 int temp;5 printf(a=%d, b=%dn, a, 5 printf(a=%d, b=%dn, a, b);b);6 temp = a;6 temp = a;7 a = b;

15、7 a = b;8 b = a;8 b = a;9 printf(a=%d, b=%dn, a, 9 printf(a=%d, b=%dn, a, b);b);10 10 11 int main()11 int main()12 12 13 int x = 10, y = 100;13 int x = 10, y = 100;14 printf(x=%d, y=%dn, x, y);14 printf(x=%d, y=%dn, x, y);15 swap(x, y);15 swap(x, y);16 printf(x=%d, y=%dn, x, y);16 printf(x=%d, y=%dn

16、, x, y);17 return 0;17 return 0;18 18 x=10, y=100x=10, y=100a=10, b=100a=10, b=100a=100, b=100a=100, b=100x=10, y=100x=10, y=100 从程序的运行结果可以看出,从程序的运行结果可以看出,mainmain函数中实参变量函数中实参变量x x和和y y的值并没有发生的值并没有发生交换,为什么会出现这样的情况呢?交换,为什么会出现这样的情况呢? 按照按照C C语言的参数传递规则,实参变量语言的参数传递规则,实参变量x x和和y y的值分别被的值分别被“单向传递单向传递”给给形参变

17、量形参变量a a和和b b,swapswap函数中对变量函数中对变量a a和和b b的值进行了交换,而变量的值进行了交换,而变量a a和和b b值的变值的变化不会影响实参变量化不会影响实参变量x x和和y y,因此造成上述程序的运行结果。,因此造成上述程序的运行结果。 上述一点,请同学们课后好好去理解。上述一点,请同学们课后好好去理解。函数的声明函数的声明函数的声明函数的声明 C C语言的函数调用要求是先定义后使用,就是要求被调用函语言的函数调用要求是先定义后使用,就是要求被调用函数定义在主调函数之前。数定义在主调函数之前。 如果在程序中自定义函数时,需要将被调函数定义在主调如果在程序中自定义

18、函数时,需要将被调函数定义在主调函数后面,就需要的函数调用之前加上函数原型声明。如果在函数后面,就需要的函数调用之前加上函数原型声明。如果在函数调用之前既无函数定义,也无函数声明,编译时会出错。函数调用之前既无函数定义,也无函数声明,编译时会出错。 函数原型声明的一般形式:函数原型声明的一般形式:类型说明符类型说明符 函数名函数名( (形式参数声明列表形式参数声明列表););例例7-47-4:定义计算圆面积的函数,在主函数中输入半径并计算面积。:定义计算圆面积的函数,在主函数中输入半径并计算面积。 1 #include 1 #include 2 #define PI 3.14159 2 #de

19、fine PI 3.14159 3 int main() 3 int main() 4 4 / /函数原型声明函数原型声明 5 double circle(double radius); 5 double circle(double radius); 6 double r, area; 6 double r, area; 7 scanf(%lf, &r); 7 scanf(%lf, &r); 8 area = circle(r); 8 area = circle(r); 9 printf(area=%.2fn, area); 9 printf(area=%.2fn, area); 10 ret

20、urn 0; 10 return 0; 11 11 12 double circle(double radius) 12 double circle(double radius) 13 13 14 return PI * radius * radius; 14 return PI * radius * radius; 15 15 函数声明中函数名后面的圆括号中可以只给出形参的类型,省略形参的函数声明中函数名后面的圆括号中可以只给出形参的类型,省略形参的名称。例如本例中第名称。例如本例中第5 5行的函数声明可以写成如下形式:行的函数声明可以写成如下形式:double circle(double)

21、;double circle(double); 如果在源程序文件的开头部分如果在源程序文件的开头部分,所有函数定义的前面进行函数声明,则,所有函数定义的前面进行函数声明,则该源程序文件中所有的函数都可以调用被声明的函数了。该源程序文件中所有的函数都可以调用被声明的函数了。7.3 7.3 7.3 7.3 数组作为函数参数数组作为函数参数数组作为函数参数数组作为函数参数 数组作为函数参数在函数之间传递数据有两种情况:数组作为函数参数在函数之间传递数据有两种情况: 一是数组元素作为函数参数,这种情况下与简单变量作为一是数组元素作为函数参数,这种情况下与简单变量作为函数的参数完全一样,数组元素的值被单

22、向传递给形参变量。函数的参数完全一样,数组元素的值被单向传递给形参变量。 另一种情况是数组名作为函数的参数,此时作为实参的数另一种情况是数组名作为函数的参数,此时作为实参的数组名将其存储的数组的首地址单向传递给作为形参的数组名。组名将其存储的数组的首地址单向传递给作为形参的数组名。例例7-67-6:编写程序,定义一个能够计算数组平均值的函数编写程序,定义一个能够计算数组平均值的函数averageaverage。在。在mainmain函数中输入一个班所有学生的考试成绩,调用函数中输入一个班所有学生的考试成绩,调用averageaverage函数计算平均成绩并输出。函数计算平均成绩并输出。 1 #

23、include 1 #include 2 double average(double array, int n); / 2 double average(double array, int n); /函数声明函数声明 3 int main()3 int main() 4 4 5 double scores40; / 5 double scores40; /假设一个班最多假设一个班最多4040人人 6 double aver;6 double aver; 7 int num, i; 7 int num, i; 8 printf( 8 printf(输入班级人数输入班级人数: );: ); 9 s

24、canf(%d, &num); 9 scanf(%d, &num); 10 printf( 10 printf(输入输入%d%d个学生成绩个学生成绩: n, num);: n, num); 11 for(i=0; inum; i+) 11 for(i=0; inum; i+) 12 12 13 scanf(%lf, &scoresi); 13 scanf(%lf, &scoresi); 14 14 15 aver = average(scores, num); 15 aver = average(scores, num); 16 printf( 16 printf(班级平均分班级平均分: %.

25、2fn, aver);: %.2fn, aver); 17 return 0; 17 return 0; 18 18 20 double average(double array, int n) 20 double average(double array, int n) 21 21 22 double sum = 0; 22 double sum = 0; 23 int i; 23 int i; 24 for(i=0; in; i+) 24 for(i=0; in; i+) 25 25 26 sum = sum + arrayi; 26 sum = sum + arrayi; 27 27 2

26、8 return sum/n; 28 return sum/n; 29 29 输入班级人数输入班级人数: 10: 10 输入输入1010个学生成绩个学生成绩: :75 80 77 83 67 95 74 88 92 6575 80 77 83 67 95 74 88 92 65 班级平均分班级平均分: 79.60: 79.60 多维数组名作为函数的参数的一般形式如下多维数组名作为函数的参数的一般形式如下 类型说明符类型说明符 函数名函数名( (类型说明符类型说明符 形参数组名形参数组名 数组长度数组长度数组长度数组长度) . . . . 形参的二维数组在定义时可以不指定数组第形参的二维数组在定

27、义时可以不指定数组第1 1维的长度,第维的长度,第2 2维的长度必维的长度必须确定须确定 例例7-87-8:编写函数:编写函数maxmax求整型二维数组中元素的最大值。求整型二维数组中元素的最大值。 1 #include 1 #include 2 int max(int array4, int row); / 2 int max(int array4, int row); /函数声明函数声明 3 void display(int array4, int row); /3 void display(int array4, int row); /函数声明函数声明 4 int main()4 int

28、 main() 5 5 6 int a34 = 1, 3, 5, 7, 4, 66, 33, 18, 6, 8, 9, 3; 6 int a34 = 1, 3, 5, 7, 4, 66, 33, 18, 6, 8, 9, 3; 7 int b24 = 11, 23, 55, 22, 6, 8, 9, 3; 7 int b24 = 11, 23, 55, 22, 6, 8, 9, 3; 8 printf( 8 printf(数组数组a: n);a: n); 9 display(a, 3); / 9 display(a, 3); /调用调用displaydisplay输出数组输出数组a a 10

29、printf( 10 printf(数组数组a a的最大值的最大值: %dn, max(a, 3); /: %dn, max(a, 3); /求求a a的最大值并输出的最大值并输出 11 printf(11 printf(数组数组b: n);b: n); 12 display(b, 2); / 12 display(b, 2); /调用调用displaydisplay输出数组输出数组a a 13 printf( 13 printf(数组数组b b的最大值的最大值: %dn, max(b, 3); /: %dn, max(b, 3); /求求b b的最大值并输出的最大值并输出 14 return

30、 0;14 return 0; 15 15 16 16 /*max/*max求求4 4列的二维数组列的二维数组arrayarray中元素最大值中元素最大值, row, row为行数为行数* */ / 17 int max(int array4, int row) 17 int max(int array4, int row) 18 18 19 int i, j, m; 19 int i, j, m; 20 m = array00; 20 m = array00; 21 for(i=0; irow; i+) 21 for(i=0; irow; i+) 22 22 23 for(j=0; j4;

31、j+) 23 for(j=0; j m) m=arrayij; 25 if(arrayij m) m=arrayij; 26 26 27 27 28 return m; 28 return m; 29 29 30 /*display 30 /*display输出输出4 4列的二维数组列的二维数组, row, row为行数为行数* */ / 31 void display(int array4, int row) 31 void display(int array4, int row) 32 32 33 int i, j; 33 int i, j; 34 for(i=0; irow; i+) 3

32、4 for(i=0; irow; i+) 35 35 36 for(j=0; j4; j+) 36 for(j=0; j4; j+) 37 37 38 printf(%4d, arrayij); 38 printf(%4d, arrayij); 39 39 40 printf(n); 40 printf(n); 41 41 42 42 数组数组a:a: 1 3 5 7 1 3 5 7 4 66 33 18 4 66 33 18 6 8 9 3 6 8 9 3数组数组a a的最大值的最大值: 66: 66数组数组b:b: 11 23 55 22 11 23 55 22 6 8 9 3 6 8 9

33、 3数组数组b b的最大值的最大值: 55: 557.47.47.47.4函数函数函数函数的嵌套的嵌套的嵌套的嵌套调用调用调用调用 C C语言的函数定义是互相平行和独立的,但函数的调用是可语言的函数定义是互相平行和独立的,但函数的调用是可以嵌套的,也就是说,在调用一个函数的过程中,又去调用另以嵌套的,也就是说,在调用一个函数的过程中,又去调用另外一个函数。外一个函数。例例7-97-9:编写程序,编写程序,使用函数嵌套定义计算使用函数嵌套定义计算 1! + 2! + 3! + 1! + 2! + 3! + + n! + n! 1 #include 1 #include 2 long fac(in

34、t n); 2 long fac(int n); 3 long sum(int n); 3 long sum(int n); 4 int main() 4 int main() 5 5 6 printf(1!+2!+3! = %ldn, sum(3); 6 printf(1!+2!+3! = %ldn, sum(3); 7 printf(1!+2!+3!+4! = %ldn, sum(4); 7 printf(1!+2!+3!+4! = %ldn, sum(4); 8 printf(1!+2!+3!+4!+5! = %ldn, sum(5); 8 printf(1!+2!+3!+4!+5! =

35、 %ldn, sum(5); 9 return 0; 9 return 0; 10 10 11 /* fac 11 /* fac函数计算函数计算n! */n! */ 12 long fac(int n) 12 long fac(int n) 13 13 14 long f = 1; 14 long f = 1; 15 int i; 15 int i; 16 for(i=1; i=n; i+) 16 for(i=1; i=n; i+) 17 17 18 f = f * i; 18 f = f * i; 19 19 20 return f; 20 return f; 21 21 22 /* sum

36、 22 /* sum求求1! + 2! + 3! + 1! + 2! + 3! + + n! */ + n! */ 23 long sum(int n) 23 long sum(int n) 24 24 25 int i; 25 int i; 26 long s = 0; 26 long s = 0; 27 for(i=1; i=n; i+) 27 for(i=1; i0n0情况下,情况下,n! = n*factotial(n)n! = n*factotial(n),问题简化为计算,问题简化为计算factotial(n-1)factotial(n-1)的的子问题,子问题的本质与原问题相同,但是

37、更加接近终止状态。如此不断递子问题,子问题的本质与原问题相同,但是更加接近终止状态。如此不断递归调用,最终达到终止状态而完成递归调用。归调用,最终达到终止状态而完成递归调用。 1 #include 1 #include 2 long factotial(int n); 2 long factotial(int n); 3 int main() 3 int main() 4 4 5 printf(5! = %ldn, 5 printf(5! = %ldn, factotial(5);factotial(5); 6 printf(10! = 6 printf(10! = %ldn, factoti

38、al(10);%ldn, factotial(10); 7 return 0; 7 return 0; 8 8 9 /* factotial 9 /* factotial使用递归方式计算使用递归方式计算n! */n! */ 10 long factotial(int n) 10 long factotial(int n) 11 11 12 if(n = 0) 12 if(n = 0) 13 13 14 return 1; 14 return 1; 15 15 16 else 16 else 17 17 18 return n * factotial(n- 18 return n * facto

39、tial(n-1); 1); 19 19 20 20 5! = 12010! = 3628800例例7-117-11:使用函数递归调用实现将一个正整数输出其二进制形式,:使用函数递归调用实现将一个正整数输出其二进制形式,例如,输入例如,输入1010,输出,输出10101010思路分析:将十进制的正整数转换成其二进制形式输出,可以采用思路分析:将十进制的正整数转换成其二进制形式输出,可以采用“除除2 2取取余,逆序排列余,逆序排列”方法。具体方法是,用方法。具体方法是,用2 2整除十进制整数,可以得到一个商整除十进制整数,可以得到一个商和余数;再用和余数;再用2 2去除商,又会得到一个商和余数,

40、如此进行,直到商为去除商,又会得到一个商和余数,如此进行,直到商为0 0时为时为止,然后把先得到的余数作为二进制数的低位,后得到的余数作为二进制数止,然后把先得到的余数作为二进制数的低位,后得到的余数作为二进制数的高位,依次排列起来。的高位,依次排列起来。 1 #include 1 #include 2 void dtob(int n); 2 void dtob(int n); 3 int main() 3 int main() 4 4 5 printf(10 5 printf(10的二进制形式的二进制形式: );: ); 6 dtob(10); 6 dtob(10); 7 printf(n)

41、; 7 printf(n); 8 printf(100 8 printf(100的二进制形式的二进制形式: );: ); 9 dtob(100); 9 dtob(100);10 printf(n);10 printf(n);11 printf(25511 printf(255的二进制形式的二进制形式: );: );12 dtob(255);12 dtob(255); 13 printf(n); 13 printf(n); 14 return 0; 14 return 0; 15 15 16 16 17 void dtob(int n) 17 void dtob(int n) 18 18 19

42、if(n/2 0) 19 if(n/2 0) 20 20 21 dtob(n/2); 21 dtob(n/2); 22 22 23 printf(%d, n%2); 23 printf(%d, n%2); 24 24 10的二进制形式的二进制形式: 1010100的二进制形式的二进制形式: 1100100255的二进制形式的二进制形式: 111111117.67.67.67.6局部变量与全局变量局部变量与全局变量局部变量与全局变量局部变量与全局变量 一般来说,一般来说,C C语言程序中可以在程序中以下地方定义变量:语言程序中可以在程序中以下地方定义变量:(1) (1) 函数体的开头部分。函数体

43、的开头部分。(2) (2) 函数头部中的形式参数变量。函数头部中的形式参数变量。(3) (3) 函数体内部的复合语句中。函数体内部的复合语句中。(4) (4) 函数的外部。函数的外部。 根据变量在程序中定义位置,可以将变量分为根据变量在程序中定义位置,可以将变量分为“局部变量局部变量”和和“全局变量全局变量” 在函数内部定义的变量称为局部变量在函数内部定义的变量称为局部变量。函数体开头部分、函数头中的形。函数体开头部分、函数头中的形式参数和函数体内复合语句中定义的变量都属于局部变量。式参数和函数体内复合语句中定义的变量都属于局部变量。 局部变量的作用域是从该变量的定义语句开始到包含该变量定义语

44、句的局部变量的作用域是从该变量的定义语句开始到包含该变量定义语句的最内层的右大括号结束为止。最内层的右大括号结束为止。 源程序文件中在函数外部定义的变量称为全局变量源程序文件中在函数外部定义的变量称为全局变量, ,全局变量作用域的全局变量作用域的起点是变量定义的位置,全局变量作用域的终点中其所在的源程序文件的结起点是变量定义的位置,全局变量作用域的终点中其所在的源程序文件的结束束。例例7-127-12:定义一个一维数组,其中存放从键盘输入的:定义一个一维数组,其中存放从键盘输入的1010个学生的考试成绩,定个学生的考试成绩,定义一个函数,当义一个函数,当mainmain函数调用此函数后,能够得

45、到考试成绩的最高分、最低分函数调用此函数后,能够得到考试成绩的最高分、最低分和平均分和平均分1 #include 1 #include 2 double max, min; 2 double max, min; 3 double average(double array, int n); 3 double average(double array, int n); 4 int main()4 int main()5 5 6 double scores10, aver;6 double scores10, aver;7 int i;7 int i;8 printf(8 printf(输入输入10

46、10个学生的成绩个学生的成绩: n);: n);9 for(i=0; i10; i+)9 for(i=0; i10; i+)10 10 11 scanf(%lf, &scoresi);11 scanf(%lf, &scoresi);12 12 13 aver = average(scores, 10); 13 aver = average(scores, 10); 14 printf(14 printf(最高分最高分: %.2fn, max);: %.2fn, max);15 printf(15 printf(最低分最低分: %.2fn, min);: %.2fn, min);16 print

47、f(16 printf(平均分平均分: %.2fn, aver);: %.2fn, aver);17 return 0;17 return 0;18 18 19 /* average 19 /* average函数求出最高分、最低分放在全局变量中函数求出最高分、最低分放在全局变量中; ; 平均分为返回值平均分为返回值 * */ / 20 double average(double array, int n) 20 double average(double array, int n) 21 21 22 double sum = 0; 22 double sum = 0; 23 int i; 2

48、3 int i; 24 max = min = array0; / 24 max = min = array0; /全局变量的值设为第全局变量的值设为第1 1个成绩个成绩 25 for(i=0; in; i+)25 for(i=0; i max) max = arrayi; / 27 if(arrayi max) max = arrayi; /更新最高分更新最高分 28 if(arrayi min) min = arrayi; /28 if(arrayi min) min = arrayi; /更新最低分更新最低分 29 sum = sum + arrayi; /29 sum = sum +

49、arrayi; /累加求和累加求和 30 30 31 return sum/n; / 31 return sum/n; /返回平均分返回平均分 32 32 输入输入10个学生的成绩个学生的成绩:89 95 87.5 99 68.5 96 59 85 73 90最高分最高分: 99.00最低分最低分: 59.00平均分平均分: 84.207.77.77.77.7变量的存储方式变量的存储方式变量的存储方式变量的存储方式 C C语言中,供用户程序运行使用的内存空间分为三个部分:程序区、静语言中,供用户程序运行使用的内存空间分为三个部分:程序区、静态存储区和动态存储区。态存储区和动态存储区。 (1)

50、(1) 程序区存放可执行的程序指令。程序区存放可执行的程序指令。 (2) (2) 静态存储区存放程序运行期间占用固定内存单元的变量,包括程序静态存储区存放程序运行期间占用固定内存单元的变量,包括程序中定义的全局变量、静态局部变量(中定义的全局变量、静态局部变量(staticstatic)等。)等。 (3) (3) 动态存储区存放程序运行期间根据需要动态分配存储单元的变量,动态存储区存放程序运行期间根据需要动态分配存储单元的变量,包括程序中定义的非包括程序中定义的非staticstatic的局部变量、函数的形式参数等。的局部变量、函数的形式参数等。 C C语言中变量的存储类别具体可以分为语言中变

51、量的存储类别具体可以分为4 4种:自动(种:自动(autoauto)、静态)、静态(staticstatic)、寄存器()、寄存器(registerregister)和外部()和外部(externextern)。)。局部变量的存储类别局部变量的存储类别 局部变量有三种存储类型:自动(局部变量有三种存储类型:自动(autoauto)、静态()、静态(staticstatic)和寄存器)和寄存器(registerregister)。)。1. 1. 自动局部变量自动局部变量 函数中的局部变量,如果没有特别声明为函数中的局部变量,如果没有特别声明为staticstatic(静态)存储类别,都(静态)存

52、储类别,都是由系统动态地分配和释放内存空间,变量存放在动态存储区中,称为自动是由系统动态地分配和释放内存空间,变量存放在动态存储区中,称为自动变量。函数中的形参也属于自动变量。变量。函数中的形参也属于自动变量。2. 2. 静态局部变量静态局部变量 如果希望函数中局部变量的值在函数调用结束后仍然保留原来的值,即如果希望函数中局部变量的值在函数调用结束后仍然保留原来的值,即系统不释放变量占用的内存空间,在下一次函数调用时,该变量保持上一次系统不释放变量占用的内存空间,在下一次函数调用时,该变量保持上一次函数调用结束后的值。此时应该使用函数调用结束后的值。此时应该使用staticstatic关键字把

53、局部变量说明成静态存关键字把局部变量说明成静态存储方式。储方式。3. 3. 寄存器变量寄存器变量 一般情况下,变量存放在内存空间中,当程序中使用变量时,由控制器一般情况下,变量存放在内存空间中,当程序中使用变量时,由控制器发出的指令把数据从内存中变量的值送到运算器,经过运算器产生的结果,发出的指令把数据从内存中变量的值送到运算器,经过运算器产生的结果,如果需要保存,再从运算器送到内存。如果程序中某些变量使用非常频如果需要保存,再从运算器送到内存。如果程序中某些变量使用非常频例例7-137-13:观察静态局部变量与自动局部变量的区别:观察静态局部变量与自动局部变量的区别 1 #include 1

54、 #include 2 void func1(); 2 void func1(); 3 void func2(); 3 void func2(); 4 int main() 4 int main() 5 5 6 printf( 6 printf(调用函数调用函数func1func1三次三次:n);:n); 7 func1(); 7 func1(); 8 func1(); 8 func1(); 9 func1(); 9 func1();10 printf(10 printf(调用函数调用函数func2func2三次三次:n);:n);11 func2();11 func2();12 func2(

55、);12 func2();13 func2();13 func2(); 14 return 0; 14 return 0; 15 15 16 void func1() 16 void func1() 17 17 18 int num = 0; 18 int num = 0; 19 num = num + 1;19 num = num + 1; 20 printf(num = %dn, num); 20 printf(num = %dn, num); 21 21 22 void func2() 22 void func2() 23 23 24 static int num = 0; 24 sta

56、tic int num = 0; 25 num = num + 1;25 num = num + 1; 26 printf(num = %dn, num); 26 printf(num = %dn, num); 27 27 调用函数调用函数func1三次三次:num = 1num = 1num = 1调用函数调用函数func2三次三次:num = 1num = 2num = 3全局变量的存储类别全局变量的存储类别 全局变量是存放在静态存储区的,它们的生命期是固定的,是程序运行全局变量是存放在静态存储区的,它们的生命期是固定的,是程序运行的整个过程。全局变量主要有的整个过程。全局变量主要有2 2

57、种存储类别:外部(种存储类别:外部(externextern)和静态)和静态(staticstatic)。)。1. 1. 外部全局变量外部全局变量 如果要在源程序文件中使用其它源程序文件中定义的全局变量,则需要如果要在源程序文件中使用其它源程序文件中定义的全局变量,则需要使用关键字使用关键字externextern说明说明2. 2. 静态全局变量静态全局变量 程序设计中如果希望某个源程序文件中定义的全局变量只能在本文件中程序设计中如果希望某个源程序文件中定义的全局变量只能在本文件中使用,不能在其它源程序中使用,则可以在定义全局变量时加上使用,不能在其它源程序中使用,则可以在定义全局变量时加上s

58、taticstatic关键关键字说明。字说明。7.87.87.87.8内部函数与外部函数内部函数与外部函数内部函数与外部函数内部函数与外部函数 C C语言程序的基本构成单位是函数,多源程序文件构成的程序中,函数的定义和语言程序的基本构成单位是函数,多源程序文件构成的程序中,函数的定义和调用也必须考虑可以调用的程序范围问题。调用也必须考虑可以调用的程序范围问题。 函数本质是全局的,定义函数的目的就是被其他函数调用。如果不回声明的话,函数本质是全局的,定义函数的目的就是被其他函数调用。如果不回声明的话,一个源程序文件中定义的函数既可以被本文件中的其它函数被调用,也可以被其它一个源程序文件中定义的函

59、数既可以被本文件中的其它函数被调用,也可以被其它源程序文件中的函数调用。根据函数能否被其他源程序文件调用,可以把函数分为源程序文件中的函数调用。根据函数能否被其他源程序文件调用,可以把函数分为内部函数和外部函数。内部函数和外部函数。1. 1. 内部函数内部函数 如果一个函数只能被其所在的源程序文件中其它的函数调用,则称为内部函数。如果一个函数只能被其所在的源程序文件中其它的函数调用,则称为内部函数。定义内部函数时,在函数头的前面加上定义内部函数时,在函数头的前面加上staticstatic关键字关键字static static 类型标识符类型标识符 函数名函数名( (形式参数列表形式参数列表)

60、 ) 2. 2. 外部函数外部函数如果在定义函数时,在函数头的前面使用如果在定义函数时,在函数头的前面使用externextern关键字进行说明,则函数为外部函关键字进行说明,则函数为外部函数。可以供其他源程序文件中的函数调用,一般形式如下:数。可以供其他源程序文件中的函数调用,一般形式如下:extern extern 类型标识符类型标识符 函数名函数名( (形式参数列表形式参数列表) ) 例如:例如:extern void process(int a, int b)extern void process(int a, int b) 7.97.97.97.9编译预处理编译预处理编译预处理编译预

61、处理 C C语言的编译预处理命令主要包括:宏定义、文件包含和条件编译。预处理命令语言的编译预处理命令主要包括:宏定义、文件包含和条件编译。预处理命令均以均以“# #”开始,命令的结尾没有分号,每条预处理命令必须占用单独一行。开始,命令的结尾没有分号,每条预处理命令必须占用单独一行。1.1.宏定义宏定义(1) (1) 无参宏定义无参宏定义 无参宏定义的一般形式如下:无参宏定义的一般形式如下: #define #define 宏名宏名 字符序列字符序列 如果源程序中使用了宏定义,编译预处理过程中,自动把源程序中出现的所有如果源程序中使用了宏定义,编译预处理过程中,自动把源程序中出现的所有“宏名宏名

62、”替换为替换为“字符序列字符序列”,这是一个纯文本替换,也称为宏替换。,这是一个纯文本替换,也称为宏替换。例如下面定义了例如下面定义了3 3个无参宏名:个无参宏名: #define PI 3.14 #define PI 3.14 #define R 10 #define R 10 #define AREA PI*R*R #define AREA PI*R*R(2) (2) 有参宏定义有参宏定义 有参宏定义的一般形式如下:有参宏定义的一般形式如下: #define #define 宏名宏名( (参数表参数表) ) 字符序列字符序列 有参宏定义在进行宏替换时,源程序出现宏名的地方都使用字符序列替换

63、,替有参宏定义在进行宏替换时,源程序出现宏名的地方都使用字符序列替换,替换时使用宏引用中的实参去替换宏定义中的形参。换时使用宏引用中的实参去替换宏定义中的形参。例如,如下定义了一个有参的宏名。例如,如下定义了一个有参的宏名。 #define MUL(a,b) (a)*(b) #define MUL(a,b) (a)*(b) 源程序中可以使用如下语句使用有参的宏:源程序中可以使用如下语句使用有参的宏: int x=3, y=4, z; int x=3, y=4, z; z=MUL(x,y); z=MUL(x,y);注意:通常需要在有参宏定义时,字符序列中参数要加上圆括号,以免进行宏替换注意:通常

64、需要在有参宏定义时,字符序列中参数要加上圆括号,以免进行宏替换时出现错误。时出现错误。(3) (3) 文件包含文件包含 文件包含也是一种编译预处理命令,其作用是把被包含的文件的内容全部引入文件包含也是一种编译预处理命令,其作用是把被包含的文件的内容全部引入到使用文件包含命令的源程序文件中。文件包含命令有以下到使用文件包含命令的源程序文件中。文件包含命令有以下2 2种形式:种形式:#include #include 或或 #include #include 文件名文件名 文件包含命令使用尖括号形式时,编译器在系统默认的路径中寻找被包含文件;文件包含命令使用尖括号形式时,编译器在系统默认的路径中寻

65、找被包含文件;使用双引用形式时,编译器先在用户程序的当前工作目录中寻找被包含文件,如果使用双引用形式时,编译器先在用户程序的当前工作目录中寻找被包含文件,如果找不到文件,再去系统默认的路径中寻找文件。找不到文件,再去系统默认的路径中寻找文件。下面是几个文件包含命令的例子:下面是几个文件包含命令的例子:#include /#include /包含系统预定义的头文件包含系统预定义的头文件#include user.h /#include user.h /包含自定义的头文件包含自定义的头文件#include func.c /#include func.c /包含自定义的源程序文件包含自定义的源程序文

66、件(4)(4)条件编译条件编译 通常情况下,源程序文件中的所有语句行都需要参与编译,并生成到目标文件通常情况下,源程序文件中的所有语句行都需要参与编译,并生成到目标文件中。如果源程序需要根据特定的条件决定一部分源代码是否参加编译,则需要使用中。如果源程序需要根据特定的条件决定一部分源代码是否参加编译,则需要使用条件编译预处理命令。条件编译预处理命令。 C C语言的条件编译预处理指令主要有三种形式。语言的条件编译预处理指令主要有三种形式。 #if #if指令指令一般形式:一般形式:#if #if 表达式表达式 程序段程序段1 1#else#else 程序段程序段2 2#endif#endif #

67、ifdef #ifdef指令指令一般形式:一般形式:#ifdef #ifdef 宏名宏名 程序段程序段1 1#else#else 程序段程序段2 2#endif#endif #ifndef#ifndef指令指令一般形式:一般形式:#ifndef #ifndef 宏名宏名 程序段程序段1 1#else#else 程序段程序段2 2#endif#endif7.107.107.107.10函数程序举例函数程序举例函数程序举例函数程序举例例例7-147-14:编写程序,从键盘输入一个较大的整数:编写程序,从键盘输入一个较大的整数n n(n6n6),验证),验证6 6到到n n之间的所有偶之间的所有偶数都可以分解为两个素数之和的形式。数都可以分解为两个素数之和的形式。例例7-157-15:使用选择排序对数组中的:使用选择排序对数组中的1010个整数按从小到大的顺序排序,使用函数实现。个整数按从小到大的顺序排序,使用函数实现。例例7-167-16:汉诺塔(:汉诺塔(hanoihanoi)问题。)问题。课后习题课后习题教材课后习题教材课后习题2 2、3 3、7 7本章结束

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号