C语言程序设计基础8_第1页
C语言程序设计基础8_第2页
C语言程序设计基础8_第3页
C语言程序设计基础8_第4页
C语言程序设计基础8_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第八章C 语言程序设计函 数1 本章要点函数的定义函数的调用函数间的数据传递变量的存储类型变量的作用范围内部函数和外部函数2C程序是函数的集合体,每个函数是一个独立的程序模块。有一个主函数,若干个子函数,程序总是从主函数开始执行。函数可集中或分散存放在一个或多个源程序文件中。所有子函数地位平等,可互相调用、自我调用。 引入函数的优点: 减少重复编写程序的工作量;使程序便于调试和阅读。函数F1 ( )main ( )F11 ( )F2 ( )F21 ( )F22 ( )C语言程序的结构8.1 函数的概念和函数的定义3数学函数 math.h字符和字符串函数 ctype.h, string.h输入/

2、输出函数 stdio.h动态存储分配函数 calloc(),malloc()形式无参函数有参函数空函数库函数用户定义函数:C函数的分类4例 输入三个整数,计算它们的和并输出运算结果。int add(int x, int y, int z) int s; s=x+y+z; return s;函数示例定义的求和函数main( ) int a, b, c, sum ; scanf(%d,%d,%d,&a,&b,&c); sum=add(a,b,c); printf( sum= %dn,sum); 调用求和函数58.1.2 函数的定义定义函数应包括的内容:(1)指定函数的名字,以便以后按名调用;(2)

3、指定函数的类型,即函数值的类型;(3)指定函数的参数的名字和类型(有参);(4)指定函数执行的操作,即函数完成的功能。在程序中用到的所有函数,必须先定义,后使用。6定义函数的一般形式类型标识符 函数名(形式参数表) 说明部分 语句若无参数,写void或空。是被初始化的内部变量,寿命和可见性仅限于函数内部不说明类型,自动按整型处理.建议都指定类型函数体(一段程序,实现函数的功能)71. 无参函数的定义形式 类型标识符 函数名( ) 说明部分 语句 例8-1 void print_message( ) printf(How are you !n); 8 例8-2 int max (int x,in

4、t y) int z; z=xy?x : y; return z; 类型标识符 函数名(形式参数表列) 说明部分 语句 int max ( x, y) int x,y; int z; z=xy?x : y; return z; 形参变量的说明(传统形式)形参变量的说明(现代形式)2. 有参函数的定义形式93. 形式参数说明形式参数: 在定义函数时函数名后面括弧中的变量名在形参表中说明的形参,在函数体中不再说明,可以同一般变量一样直接使用。 形参调用前不占内存单元,调用时分配内存单元。调用结束后释放。形参是函数的内部变量,只在函数内部才有意义。对每个形参必须指明其名字和数据类型。多个形参用逗号分

5、隔。10例:有函数调用语句: int i=3; printf(”%d,%d”,i,+i);输出结果为:4,4 分析输出函数的结果:自右向左:4,4自左向右:3,4避免这种不确定性:改为: int i=3, j; j=i; printf(”%d,%d”,i,+j);输出结果为:3,4118.1.3 函数的调用 1. 函数调用的一般形式为: 函数名(实际参数列表); 或 函数名(实际参数列表)说明:实参必须有确定的值,可以是常量、变量、表达式及函数调用。实参与形参的类型、个数、顺序必须一致。多个实参用逗号分隔。 2. 执行过程:计算各个表达式(TC2.0,VC+6.0实参求值顺序按自右至左);把得

6、到值赋给对应的形参;执行函数体;遇到return语句或执行完最后一条语句,返回到函数调用处.12(1) 函数语句: (把函数调用作为一个语句) 一般形式:函数名(实际参数表); 使用情况:这种方式常用于调用一个可以忽略返回值或没有返回值的函数,只要求函数完成一定的操作。 例如: print_message( ); 3. 函数调用的具体方式(2) 函数表达式:(函数调用出现在一个表达式中) 一般形式:变量名=函数表达式 使用情况:这种表达式称为函数表达式。要求函数带回 一个确定的值参加表达式的运算。 例如:c=3+max(a, b); d=pow(c, i); e= f(x1,x2,x3),(y

7、1,y2); 函数有几个参数?13 值传递: 在函数调用时,实参将其值传递给形参。 实参对形参的数据传递是“值传递”,即单向传递,只由实参传递给形参,而不能由形参传回来给实参。 实参与形参占用不同的单元。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。在执行一个被调用函数时,形参的值如果发生变化,并不会改变主调函数中实参的值。8.1.4 函数参数的传递方式 值传递的优点:被调用的函数不可能改变调用函数中变量的值,而只能改变它的局部的临时副本。 值传递的缺点:每个形式参数仅能传递一个数据,不适用需要在函数之间传递大量数据。 地址

8、传递:将实参的地址传递给形参,实参和形参指向同一内存空间,对形参的修改,可以直接影响实参。14例8-3 编写函数交换两个变量的值。 #include void swap ( int x, int y) int temp; temp=x; x=y; y=temp; printf ( x=%d, y=%dn, x, y); int main ( ) int a, b; a=5; b=10; printf ( a=%d, b=%dn, a, b); swap(a, b); printf ( a=%d, b=%dn, a, b);运行结果:a=5 ,b=10 x=10 ,y=5a=5 ,b=10158

9、.1.5 函数的返回值 2. 函数的返回值语句 一般形式: return 表达式; 或 return (表达式); 功能:退出函数,将表达式的值带回主调函数,回到程序原来的位置继续执行。 return 语句也可以没有表达式,其作用是使程序执行的流程返回到调用函数。 定义:通过函数调用使主调函数得到一个确定 的值,称为函数的返回值。16说明:return语句只能把一个返回值传递给调用函数。返回值的类型为定义的函数类型,若return语句中表达式类型与函数类型不一致,以函数类型为准。返回值可以是有确定值的常量、变量或表达式,也可以是地址。当返值是地址时,应该用指针接受。无返回值的函数,定义为voi

10、d类型(无类型函数)。一个函数中可以有多个返回语句。exit()函数由ANSC C定义的,功能是终止和关闭所有程序,结束程序执行,忽略返回值。0 为正常退出 非0 为非正常退出。17 main( ) int a,b,c; scanf (“%d,%d”,&a,&b); c=max(a,b); printf(“Max is %d”,c); 例8-4 int max(int x, int y) int z; z=xy? x:y; return(z); 形参:通知系统 要预留内存位置.实参:在运行时把值传给函数.把函数的 结果赋给函数名形参与实参、函数名与返回值之间的关系18例8-5用函数计算浮点数x

11、的n次方,其中n为整型(n=0)double power(double x, int n) double p=1; int i; if(n0) for(i=1;i=n;i+) p=p*x; return p;main() int n; double x; scanf(“%d%lf”,&n,&x); printf(“%f”, power(x,n); 19例8-6编写函数,将一个给定的整数转换成字符串。 #include void to_str(int n) char string10; int i=0; if(n0) stringi+=n%10+0; n/=10; while(-i=0) put

12、char(stringi);int main() printf(The converted string: ); to_str(-123); return 0;运行结果:The converted string:-12320例8-7 编写函数,求1+1/2+1/3+1/n的值,并在主函数中调用它。#include double count(int n) int i; double sum=0; if(n=0) printf(Data error!n); return 0; else for(i=1;i=n;i+) sum+=1.0/i; return sum; int main() int n

13、; double s; printf(Please input the value: ); scanf(%d, &n); s=count(n); printf(s=%6.2lfn, s);运行结果:Please input the value:5s= 2.28218.1.6 函数的声明 问题的提出:C语言程序可由若干文件组成,每一个文件可以单独编译。一个源程序文件由一个或多个函数组成。在一个函数中调用另一个函数需要具备如下条件:1)函数必须是已经定义的函数;2)如果使用库函数,应该在文件开头包含库函数的信息;3)若函数使用在定义之前,必须在调用函数前对函数进行声明。 同变量一样,函数的调用也应

14、该遵循“先说明,后使用”的原则。 1. 函数声明的一般形式: 类型标识符 函数名(类型1 形参1,类型2 形参2,);功能:通知编译程序函数值类型、参数个数及类型,为编译程序进行类型检查提供依据。22main() float add(float x,float y); float a, b, c; scanf(“ %f, %f”, &a, &b); c=add(a,b) ; printf(“ sum is %f ”, c );/*定义add函数*/float add (float x,float y) float z; z=x+y; return (z); 对被调用函数的说明作为表达式被调用2

15、32. 函数声明和函数定义的区别 函数声明的作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。 函数定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。 函数声明与函数定义的首部唯一区别:函数说明语句的( )之后必须有分号,而函数定义头部的( )之后没有分号。24(1) 被调用函数在主调函数之前定义 float add (float x, float y) float z; z=x+y; return (z); main() float a, b; scanf(“ %f, %f,

16、 “&a, &b); printf(“ sum is %f ”, add(a, b) ); 3. 可省略被调用函数声明的二种情况 25(2) 在所有函数定义之前说明char letter( char,char);float f(float,float );int i(float,float);main( ) .char letter (char c1,char c2)float f(float x,float y)int i(float,float)在所有函数之前说明函数类型定义函数letter、f和i268.2 数组作函数参数数组元素可以作函数的实参 数组元素作为表达式的组成部分做函数的实参

17、可以单向将值传递给形参。 例如: int a10; x=power( a6,5);数组名可以作函数的实参和形参 实现批量数据的传递27一维数组作函数参数,形参的写法为: 类型说明符 形参数组名数组长度例如: float average(float array10) main() float b10;int i; for(i=0;i10;i+) scanf(“%f”,&bi); average(b); 8.2.1 一维数组作函数参数说明:形参和实参分别定义数组数组做函数参数时,实参用数组名, 必须有确切值实参数组和形参数组类型应一致。28说明:实参数组和形参数组大小不一定一致,一维形参数组可以不

18、指定大小。数组名除作为变量的标识外,还代表该数组在内存中存放区域的首地址。数组名做函数实参与形参之间是“地址传递”,实参数组将数组的起始地址传递给形参数组。编译系统不再为形参数组分配存储单元。在函数体中对形参数组的元素操作时就是对实参数组的元素进行操作。形参数组各元素的值发生变化会使实参数组各元素的值发生同样的变化。数组名作函数参数可实现大量数据的传递,无须返回数组值。29例8-8 阅读如下程序,给出打印结果。 void swap( int a ) int t; t=a0; a0=a1; a1=t; main( ) int b2=1,2 ; swap(b); printf(“b0=%d,b1=

19、%dn”,b0,b1); 结果:程序运行演示可不定义 长度b数组a数组在调用函数过程中改变了原数组的值,实参数组与形参数组共享一组存储空间,地址传递30例8-9:编写函数用选择法对数组中10个整数由小到大排序.程序设计思想:函数sort(array, n) :实现数组元素由小到大排序。主程序 :输入array数组,调用 sort 函数比较,输 出排序后的array数组。void sort (int array , int n) int i, j, k, t; for (i=0; in-1; i+) k=i; for (j=i+1; jn; j+) if (arrayjarrayk) k=j;

20、if (k!=i) t=arrayk; arrayk=arrayi; arrayi=t; 用另外一个参数表示数组的长度31main ( ) int a10, i; printf(“enter array: n”); for (i=0; i10; i+) scanf (“ %d ”,&ai); sort(a, 10); printf(“the sorted array: n”); for (i=0; i10; i+) printf (“ %d ”, ai); printf(“n”);由于地址传递,实参数组 a 改变数组名做参数的好处:由于只需复制一个地址值,而无须复制全部需要处 理的数据,因此节

21、约存储空间并提高效率。 由于主调函数和被调函数是在相同的内存区域上对 数据进行操作,因此可以实现数据的同步更新。 函数调用32例8-10 将给定字符串复制到另一字符串。#include “stdio.h”void strcopy(char str1 ,char str2 ) int i=0; while(str1i!=0) str2i=str1i; i+; str2i=0;main() char s150,s250; printf(“Input string s1:”); gets(s1); strcopy(s1,s2); printf(“%s”,s2);33【例8-11】函数del(s, i

22、, n)的功能是从字符串s中删除从第i个字符开始的n个字符。主函数调用del函数,从字符串management中删除从第3个字符开始的4个字符,然后输出删除子串后的字符串。void del( char s , int i, int n) int j, k, length=0; while(slength!= 0) A ; j=-i; k=i+n; while(klength) sj+=sk+; sj= 0;main( ) char str=management; del( B ); printf(The new string is: %sn, str);答案 A: length+ B: str

23、,3,4348.2.2 二维数组作函数参数二维数组作函数参数,形参的写法为: 类型说明符 形参名 数组长度1 数组长度2说明:形参数组定义时可以指定或省略第一维的大小 例如 : int array 310; 或 int array 10; int array 3 ; 和int array ;错误 实参数组可以大于形参数组 例如:实参数组定义为:int array 510; 形参数组定义为:int array 310; 这时形参数组只取实参数组的一部分,其余部分不起作用。35例8-12 编写函数,求3*4矩阵中的最大值。 int max_value(int array 4) int i, j,

24、max; max=array00; for(i=0 ; i3 ; i+) for(j=0; jmax) max=arrayij; return (max); int main() int a34=1,3,5,7,2,4,6,8,10,12,15,17; printf(“max=%dn”,max_value(a); 函数调用368.3 函数的嵌套调用和递归调用8.3.1 函数的嵌套调用嵌套定义:在定义一个函数时,该函数体内包含另一个函数的定义。嵌套调用:在调用一个函数的过程中,又调用另一个函数。 C语言不能嵌套定义,但可以嵌套调用!37main函数调用A函数结 束A函数调用B函数B函数19287

25、3456 两层嵌套的例子38 8.3.2 函数的递归调用f 函数调用 f函数1. 递归的概念: 在调用一个函数的过程中直接或间接地调用该函数本身。直接调用:int f(x)int x; int y,z; z=f(y); return (2*z); 39int f1(x)int x; int y,z; . z=f2( y); return (2*z); int f2(t)int t; int a,c; . c=f1(a); return (3+c); 间接调用:f 1函数调用 f2函数f 2函数调用 f1函数40递归函数的执行过程: -递归调用:记住本次现场,递归调用。 -终了调用:返回上次调用

26、现场。特点: -是无终止的递归调用,因此,应该给定一 个限制递归次数的条件。 -结构简练。41float fac( int n) float f; if(n0) printf(“n1)例8-13 用递归法求n!调用阶乘函数不能赋给函数名42递归函数fac的求解过程,以求9的阶乘为例:fac(9)=9*fac( 8)fac(8)=8*fac( 7)fac(2)=2*fac( 1)fac(1)=1fac(9)=9*fac( 8)fac(8)=8*fac( 7)fac(2)=2*1fac(3)=3*fac( 2)fac(3)=3*2*1下推回代43例8-14 用递归法将一个整数n转换成字符串。例如输

27、入256,应输出“256”,n的位数不固定,可以是任意位数的整数。void tranvers(int n) if(n/10!=0) tranvers(n/10); printf(%c,n%10+0); main( ) int n; printf(“please input an integral number”); scanf(%d,&n); if(n0) printf(“-); n=-1*n; tranvers(n); 44main()函数第一次调用tranvers函数递归函数tranvers的求解过程示意图第二次调用tranvers函数第三次调用tranvers函数tranvers(25)

28、输出字符2tranvers(2)输出字符5输出字符6tranvers(256)结束45变量的数据类型 char 型 int 型 float 型 double 型总结:数据类型决定为变量分配的内存单元的长度,数据的存放 形式。(从程序设计角度,决定了可以表示的数的范围)问题:1. 何时为变量分配内存单元? 2. 变量位于内存的什么位置? 3. 变量的有效作用范围? 8.4 变量的作用域和存储方法(VC+6.0环境)46 变量的作用域和生存期: 变量的作用域 指一个变量在程序中的有效范围。(也称为可见性) C语言规定:凡是在函数内定义的变量,它的作用域仅仅是包含这个变量定义的复合语句;而在函数体外

29、定义的变量,它的作用域是从定义点到文件尾。 变量的生存期 指程序在执行期间,变量存在的时间间隔,即从给变量分配内存,至所分配内存被系统收回的那段时间。 C语言规定:凡是出现在静态数据区的变量,生存期都是从程序开始执行到程序结束;而出现在静态区之外的变量,生存期仅仅是从函数开始执行到函数执行结束这段时间。471.局部变量(内部变量) 定义:在函数内部定义的变量,只能在本函数内部使用。 说明(避免了函数间的相互干扰,增加了函数的独立性)主函数 main 定义的变量只在主函数中有效,主函数不能使用其它函数定义的变量。不同函数可以使用相同名字的变量。形式参数也是局部变量。可以在一个函数内部,也可以在复

30、合语句中定义变量,这些变量只在本复合语句中有效。8.4.1 局部变量和全局变量char search(char s) char ch; int k; 变量s、ch、k的作用域编译系统不为局部变量分配内存单元,只是当被调用时,根据需要分配临时单元,调用结束,空间释放。48例:main()int m,n; int x,y;变量x,y的作用域变量m,n的作用域49阅读以下程序,写出程序的运行结果。main() int i=3, j=2, k; k=i+j; int k=8; if(i=4) printf(%d, , k); else printf(%d, , j); printf(%d, %d,i,

31、k); 2,3,5502. 全局变量定义:在函数之外定义的变量是全局变量(外部变量)。语法:类型说明 变量名 ;使用范围:可以为本文件中所有的函数公用。从定义变量的位置开始到本文件结束,这段程序中的函数可直接使用全局变量,int a,b=3;main( ) float k;char str(char s20) 全局变量a、b的作用域全局变量k的作用域51 int p=1,q=5; /*外部变量*/ f1( int a) /*定义函数*/ int b,c; char c1,c2; /*外部变量*/ f2( int a, int b) /*定义函数*/ . main() int m,n 全局变量c

32、1、c2的作用范围全局变量p、q的作用范围52例如:#include “stdio.h”int a=7,b=10;main( ) int a=5,c; c=a+b; printf(“c=%dn”,c); 在同一源文件中,全局变量和局部变量可以同名,在局部变量的作用范围内,全局变量不起作用。C=15全局变量局布变量局部变量全局变量53优点:函数间数据联系:同一文件中的一些函数引用全局 变量,当某个函数中改变了全局变量的值,其它函数中的全局变量值也随之改变。函数可以得到多个返回值。(在所有函数之外说明的变量是全局变量,它在所有函数中都是可见的。利用全局变量的这个特性,可以在函数间传递数据。)缺点:

33、全局变量在程序的全部执行过程中都占用存储单元。降低函数的通用性。使用过多,降低程序的清晰性。 全局变量应尽可能少用。 54 例8-15 编写函数,利用全局变量求一维数组中正数的平均值和负数的平均值传递给调用函数输出。#include float zaver=0,faver=0;void saver(int array ,int n) int i,z=0,f=0; for(i=0 ; i0) zaver+=arrayi;z+; if(arrayi0) faver+=arrayi;f+; if(z!=0) zaver=zaver/z; if(f!=0) faver=faver/f; main()

34、int a10=1,-3,4,6,-2,7,9,-8,-5,0; saver(a,10); printf(“正数平均值=%f,负数平均值=%fn”,zaver,faver);55下面程序的运行结果是( )。#include “stdio.h”int x1=30,x2=40;void sub(int x,int y) x1=x;x=y;y=x1;main() int x3=10,x4=20; sub(x3,x4); sub(x2,x1); printf(“%d,%d,%d,%dn”,x3,x4,x1,x2);答案10,20,40,40 56 变量的存储类别静态存储方式:程序运行期间分配固定存储空

35、间的方式。动态存储方式:程序运行期间根据需要进行动态的分配存储空间的方式。程序区静态存储区动态存储区全局变量,局部静态变量形式参数局部变量(自动)函数调用的现场保护和返回地址8.4.2 变量的存储方法57动态存储变量特点 函数开始调用时为变量分配存储空间,函数结束时释放这些空间。一个程序两次调用同一函数,其中同一个局部变量的内存地址可能不同。静态存储变量特点 在 静态存储区分配存储单元,整个程序运行期间都不释放。变量存贮类型有四种:自动变量(auto)静态变量(static)外部变量(extern)寄存器变量(register)auto、static、extern和register为存贮类型说

36、明符。58(1)自动变量 (auto) 函数中的局部变量,不做任何存储类别的说明都为自动变量。 定义形式:auto 类型说明符 变量名 ; 说明:“auto”可以省略。 以前所使用的全部变量都是自动变量。 自动变量必须在一个函数体的内部。 函数的形参也是自动变量。 例如:int b, c=3 等价于 auto int b, c=3; 作用域:包含变量定义的复合语句或所说明的函数内部 ; 在函数被调用时才存在,从函数中返回时即消失, 值也仅限于说明它的函数,在其它的函数中不能存取, 在两个不同的函数中可以分别使用同名的变量。1.局部变量的存储方法59(2)局部静态变量 定义形式:在变量名前面加

37、关键字static static 类型说明符 变量名;局部静态变量编译时赋初值,每次调用时不赋初值,只保留调用结束时变量的值。如果不赋初值,编译时自动赋0值。局部静态变量只允许所在函数引用,其它函数不能引用。其值整个程序运行期间都不释放。自动变量不赋初值,其值不确定。每调用一次,重新赋值一次。60例如:int f(int a) int b=0; static int c=3; b=b+1; c=c+1; return( a+b+c);main( ) int a=2 , i; for(i=0; i3; i+) printf(“%d,”,f(a);运行结果为: 7 ,8 ,9第一次调用开始第一次调

38、用结束第二次调用开始0b34410c局部静态变量61例如:#include “stdio.h”int fun(int x, int y) static int m=0, i=2; i+=m+1; m=i+x+y; return m; main() int a=2,b=3; printf(%d, , fun(a,b); printf(%dn, fun(b,a); 8,17运行结果:62(3)寄存器变量 (register) 直接放置在运算器的寄存器中的变量称为寄存器变量. 定义形式: register 类型说明符 变量名; 作用:对于使用频繁的变量,定义为寄存器变量,不必从内存而是直接从寄存器中

39、取出参加运算,提高程序执行效率。 说明:只有局部自动变量和形式参数可作为寄存器变量,其它如局部静态变量和全局变量不可以。属于动态存储方式,函数开始调用时为变量分配寄存器空间,函数结束时释放寄存器空间。只有int、char和指针类型可定义为寄存器变量,而long、double和float型变量不能设定为寄存器型 。可用于变量空间分配的寄存器个数依赖于具体的机器。通常为2到3个,若在一个函数中说明多于2到3个寄存器变量,编译程序会自动地将它们变为自动变量。 632. 全局变量的存储类型(外部全局变量、静态全局变量)(1)外部全局变量 在多个源程序文件的情况下,如果在一个文件中要引用在其它文件中定义

40、的全局变量,则应该在需要引用此变量的文件中,用extern做说明。例如:prog1.c的内容如下:int a;main( ) x=6; f1( );void f1( ) a+=2; printf(a=%dn, a); f2( );prog2.c的内容为:extern int a;void f2( ) a+; printf(a=%dn, a); 64(2)静态全局变量 在一个文件中定义的全局变量仅限于本文件引用,而不能被其它文件访问,则可以定义为静态全局变量。 例如: static int x; 说明: 外部全局变量与静态全局变量在同一文件内的作用域一样外部全局变量可以被多个文件引用,而静态全局

41、变量仅在定义它的文件内有效,在程序的其它文件中不可使用。 例如:file1.c file2.c static int a ; extern int a; static int a只能用于file1.c ,虽然file2.c中将 同名变量 int a说明为extern,但仍无法使用file1.c 中的 a变量。658.5 内部函数和外部函数1 . 内部函数(静态函数)定义:如果一个函数只能被本文件中其它函数调用,称为内部函数。定义格式: static 类型标识符 函数名(形参表)函数体 例如:static int fun(a, b) 作用:函数的作用域限于所在文件,不同文件中同名函数互不干扰,便

42、于程序的格式化。66 2. 外部函数定义:如果一个函数允许被其它文件调用,称为外部函数。定义格式: extern 类型标识符 函数名(形参表)函数体 例如:extern int fun(int a, int b) 或 int fun(int a, int b) 通常不加 static 标识符的函数都是外部函数。673.标号的生存期及作用域生存期 在C语言中,由于函数的生存期是全程的,即从程序开始至程序结束,标号是函数的一部分,标号的生存期自然是全程的。作用域 C语言规定,标号的作用域仅为定义标号的函数,即不允许用goto语句从一个函数转向另一个函数。 68有关函数的类型1 函数的类型是函数返回

43、值的类型2 C要求函数定义的类型,说明的类型和函数定义类型一致3 定义的类型与返回值类型不一致时,以定义为准4 不定义函数类型,系统默认是int。(VC+6.0必须指定函数类型)5 不需返回任何返回值时,应定义无类型void。 总 结69有关函数的参数1 定义函数时,括号内为形参2 调用函数时,括号内为实参3 实参与形参需类型相同,个数相等4 形参在函数被调用时才分配存储空间,有值5 实参在主调函数内有值,求值顺序是从右向左6 实参与形参是单向的数值传递7 如果实参与形参都是数组名,是地址传递8 实参数组与形参数组类型相同,个数可以不同函数间的数据传递(三种传递方式):返回值、参数、全局变量。

44、701 函数可以作运算分量,作其他函数的参数,可构成语句2 函数调用可以嵌套3 函数中的return语句可以带回一个返回值有关变量从变量的作用域: 局部变量 全局变量从变量值保留的期限: 静态存储变量 动态存储变量从变量在硬件上的位置: CPU寄存器 内存中静态区 内存中动态区有关函数的调用71存储特性特点生存期作用域未初始化时值自动变量定义它的函数 (局部变量)随机数外部变量整个程序中多个文件中的多个函数(全程变量 )0静态局部全局整个程序 定义它的函数(静态局部)定义它的文件(静态全程) 0 0寄存器变量定义它的函数随机数72file1.c程序:int plus(int x,int y)

45、int z; z=x+y; return z;例:现已定义函数plus求两个数的和,包含在文件file1.c中,在file2.c程序文件中要调用此函数,请将下列程序补充完整,使程序正确。file2.c程序:# include _A_main() int a=4,b=5,c; _B_ plus(int ,int); c=plus(a,b); printf(“a+b=%d”n”,c);答案 A: “file1.c” B: extern 73 例 下面程序由两个文件组成,请分析运行结果。/* 文件一 prog1.c*/#include stdio.h#include prog2.cint x=10,

46、y=10; extern void sub() ; void add() int y=5; y=10+x; x*=2; printf(add:y=%d; ,y); main() x+=5; add(); sub();printf(main:x=%d; main:y=%dn,x,y); /* 文件二 prog2.c*/#include “stdio.h”extern int x;void sub() int y=5; x-=y; printf(“sub:y=%d;”,y); 运行结果:74C的源程序 预处理 编译 目标程序 (*.C) _ (*.OBJ)编译系统中有 : 预处理程序 编译程序宏替

47、换 #define N 20 文件包含 #include条件编译 #if( . ) C中的预处理命令分类8.6 编译预处理75宏定义有两种类型:字符串替换和带参数的宏替换 ( 1) 字符串宏替换 功能:在预处理时 ,将程序中宏定义之后出现的所有的宏名,用宏替换体代替。宏替换名宏替换体例如:#define PI 3.14159 格式:#define 宏名宏定义字符串 C的编译程序调用预处理程序检查有否宏名,若有,用宏替换体将其替换,完成之后,将替换后的源程序交给编译程序。1.宏定义76 用途: 提高程序的可读性,便于修改、调试。 - 符号常量,如 PI、 数组的长度 - 为程序书写带来方便(将程

48、序中多次出现相同内容写成宏)#define N 10 /* 编译之前用10替换所有的N */.int aN 说明: 通常放在程序开头,不加分号 是代替,不是赋值(不作语法检查) 可将多个语句或表达式定义为一个宏替换 为区别变量和关键字,习惯用大写77#define R 3.0#define PI 3.145926#define L 2.0*PI*R#define S PI*R*R 双引号中的不替换 有效范围,从定义开始到程序结尾例: #define PI 3.14159main( ) printf (“PI=%fn”,PI); 结果:PI=3.14159main( ) printf(“PI=%sn”,”PI”); 可以嵌套,后定义的宏可以包含先定义的宏名结果:PI=PI78(2) 带参数的宏定义 带参数的宏不仅能进行字符串代替,而且还能进行参数代换。 格式: #define 宏名(参数表) 表达式 功能: 带参数的宏将一个带形参的表达式定义为一个带参数的宏名,预处理程序对程序中所有带实参表的宏名进行宏展开替换,用表达式代替宏名,用参数表中的实参代替表达式中对应的形参。例:#define S( a, b) a*b程序中 S(3, 2) 3*279 用途:用带参数的宏可以代表

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论