




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 C语言程序设计教程 第6章 函数与编译预处理 2021-8-42 2021-8-43 基本概念 基本模块基本模块 模块模块模块模块模块模块 模块模块模块模块模块模块模块模块模块模块模块模块 C语言程序设计教程 第6章 函数与编译预处理 2021-8-44 C语言程序设计教程 第6章 函数与编译预处理 2021-8-45 任务、模块与函数的关系:一个大 任务分成多个功能模块, 功能模块则由一个或多函数实现。 模块化的程序设计是靠设计函数模块化的程序设计是靠设计函数 和调用函数实现的和调用函数实现的。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-46 任务:输入三个数,从大到小的
2、顺序的输出。如果大 于等于85,在该数后面输出A,小于85且大 于等于70,则输出B,小于70且大于等于60, 输出C,如果小于60,则输出D。 思路:scanf()输入分数 另建一个排序函数 判断并输出等级函数 打印分数及等级的函数 虽然也可以由一个主函数来完成,但这样做可读性及操 作性会更好。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-47 C语言程序设计教程 第6章 函数与编译预处理 2021-8-48 void sortabc(a,b,c) float *a,*b,*c; float t; if (*a *b) t=*a; *a=*b; *b=t; /* 交换a,和b
3、 的值 */ if (*b *c) t=*b; *b=*c; *c=t; /* 交换b,和c 的值 */ if (*a =85) return(A); else if (x=70) return(B); else if (x=60) return (C); else return (D); C语言程序设计教程 第6章 函数与编译预处理 2021-8-411 void putabc(a,b,c) float a,b,c; char g; g = grade(a); /*判别等级 */ printf(%6.1f :%c,a,g); g = grade(b); printf(%6.1f:%c,b,g
4、 ); g = grade(c); printf(%6.1f:%c,c,g); C语言程序设计教程 第6章 函数与编译预处理 2021-8-412 模块独立规模适当 层次分明功能专一 C语言程序设计教程 第6章 函数与编译预处理 2021-8-413 独立性原则表现在模块完成独立的功能, 和其它模块间的关系简单,各模块可以单独调 试。修改某一模块,不会造成整个程序的混乱。 每个模块完成一个相对独立的特定子功能。在对任务逐步 分解时,要注意对问题的综合。例如, 一些模块的相似的 子任务,可以把它们综合起来考虑,找出它们的共性,把它 们做成一个完成特定任务的单独模块。 每个模块有特定功能 C语言程
5、序设计教程 第6章 函数与编译预处理 2021-8-414 模块之间最好只通过数据传递发生联系,而不发生控制联 系。 例如,C语言禁止goto语句作用到另一个函数, 就是 为了保证函数的独立性。 每个模块力求简单每个模块力求简单 C语言程序设计教程 第6章 函数与编译预处理 2021-8-415 模块内使用的数据,对于不需要这些数据的其它模块来说, 应该不允许使用;在一个模块内的变量的修改不会影响其 它模块的数据。即模块的私有数据只属于这个模块。C语言 的局部变量,就是满足模块独立的的需要。 每个模块应用独立变量 C语言程序设计教程 第6章 函数与编译预处理 2021-8-416 模块不能太大
6、,但也不能太小。模块的功 能复杂,可读性就不好,而且也违背独立 性原则。但如果做得太小,实际上也会 复杂各个模块间反复调用,可读性也会 降低。这点需要慢慢积累经验,好好把 握。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-417 算 法 简 介算 法 简 介算 法 简 介 什么是算法? 通俗地说,算法是解决一类特定问题的方法 和步骤。 算法是一个有限操作的序列。 算法的每一步都是确定的。 算法的每一步计算机都能操作。 有一个或多个的输入或输出。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-418 算法描述的任务是将解题步骤和方法用一定的形式表示 出来,要清楚、准
7、确、严谨,还要可读性好,方便实现。 算法两大要素: 一是操作,用类计算机语句或自然语言描述。 二是控制结构,描述算法一般可以用流程图描述。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-419 2021-8-420 开始 输入a,b ab 交换a,b 输出a 结束 非0 0 图6.3 找出a,b两数中的较大者算法流程图 C语言程序设计教程 第6章 函数与编译预处理 2021-8-421 C语言程序设计教程 第6章 函数与编译预处理 2021-8-422 说明: 1、一个源程序文件通常由一个被称为main的主函数和若 干个其它函数组成。编译时以源程序文件为单位进行编 译,而不是以函
8、数为单位。 2、一个程序可以由一个或多个源程序文件组成。 3、程序的执行从main函数开始,由主函数调用其它函数, 其它函数也可以相互调用,程序流程最后回到main函数, 在main函数中结束整个程序的运行。 4、一个(主调)函数 可以多次调用多个 (被调)函数。同 一个函数也可以被 一个或多个(主调) 函数调用任意多次。 下图说明一种调用 关系: main abc f defghid C语言程序设计教程 第6章 函数与编译预处理 2021-8-423 5、main函数是系统定义的,只能由系统调用。 6、所有函数在定义时都是平行的,相互独立(一个函数并 不从属于另一个函数),即函数不能嵌套定义
9、,但可以 相互调用。 7、 函数分类 使用情况 库函数(标准函数): 由系统提供,用户不必自己定义,可以直接使用 用户自定义函数:解决用户的专门需要 函数形式 无参函数: 主调函数与被调函数之间没有数据传递 有参函数: 主调函数与被调函数之间有数据传递 任务情况 带返回值 不带返回值 C语言程序设计教程 第6章 函数与编译预处理 2021-8-424 C语言程序设计教程 第6章 函数与编译预处理 2021-8-425 想要调用标准的库函数,就必须include。 #include main() printf(“%d”,1024*768); 调用printf函数时, 必须include C语言程
10、序设计教程 第6章 函数与编译预处理 2021-8-426 可以把完成一个任务的过程写成函数。 int A_to_a(int capital) int small; if (capital=A return small; 返回值类型名 函数名 注意不要与已有库函数重名 参数说明和参数列表 调用函数时输入参数的格式要与之相同 定义局部变量 最好只使用局部变量,这样将方便调试。 返回值 如果不需返回则可return 0;另外请注意这样的判断,如写成Acapitalb) y=a; else y=b; C语言程序设计教程 第6章 函数与编译预处理 2021-8-430 自定义函数在调用前应先声明。使系
11、统知道将要用到某个 函数及它的类型,以便处理。函数声明应与该函数定义时 给出的函数类型与名字、形参的个数、类型、次序相一致。 #include “stdio.h” void main() float x,y; int n; float power (float x, int n); scanf(%f,%d, y = power(x, n); printf(“%8.2f”,y ); float power( float x, int n) int i; float t=1; for(i=1; i=n; i+) t = t * x; return t; C语言程序设计教程 第6章 函数与编译预处理
12、 2021-8-431 C语言程序设计教程 第6章 函数与编译预处理 2021-8-432 C语言程序设计教程 第6章 函数与编译预处理 2021-8-433 C语言程序设计教程 第6章 函数与编译预处理 2021-8-434 同样的,在调用 m=max(a,b)时,其形参 的值是a和b 而m将会得到y的值 调用时: m=max(3,6); m=max(a,b); 括号里是形式参数 返回值 括号里是实参 在这一句调用时, 形参的值是3和6其返回值y将被赋给 调用语句中的m C语言程序设计教程 第6章 函数与编译预处理 2021-8-435 C语言程序设计教程 第6章 函数与编译预处理 2021
13、-8-436 C语言程序设计教程 第6章 函数与编译预处理 2021-8-437 C语言程序设计教程 第6章 函数与编译预处理 2021-8-438 C语言程序设计教程 第6章 函数与编译预处理 2021-8-439 函数的功能就是输出函数的功能就是输出35个个- 调用调用: putline( ); 应该的语句形式应该的语句形式 i=putline( ); 是错的是错的 C语言程序设计教程 第6章 函数与编译预处理 2021-8-440 a=function(x,y); 或者 function(x,y); 取返回值 只是操作 解决更复杂问题时可以嵌套调用。 )!( ! ! nmn m C n
14、m long fac(int k) long f=1; int i; for(i=1;i=n;i+) f=f*i; retrun f; long combination(int n ,int m) long c; int i; c=fac(m)/(fac(n)*fac(m-n) ); retrun c; 主函数: main( ) int n,m; long c; scanf(“%d,%d”, c=combination (n,m); prnit(“%ld”, c); 理论上可以a(b(d(e(x),c(f) 般嵌套无数层。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-441 语
15、言的函数定义都是互相平行的、独立的,即不允许嵌 套定义函数;但是,可以嵌套调用函数,即程序在调用一个函 数的过程中,该被调函数又可以调用其它函数。 下图表示函数的嵌套调用: main函数a 函数b 函数 调用a函数调用b函数 结束 C语言程序设计教程 第6章 函数与编译预处理 2021-8-442 例:求1!+2!+3!+n! #include void main( ) float sum(int); float add; int n; scanf(%d, add=sum(n); printf(nAdd=%e., add); float sum(int n) float fac(int); i
16、nt i; float s=0; for (i=1; i=n; i+) s+=fac(i); return(s); float fac(int i) float t=1; int n=1; while (n=i) t=t*n; n+; return(t); eg607.cpp C语言程序设计教程 第6章 函数与编译预处理 2021-8-443 例2:用弦截法求方程x3-5x2+16x-80=0的根 #include float f(float x) float xpoint(float x1, float x2) f(x) float root(float x1, foat x2) xpoin
17、t(x1, x2); void main( ) root(x1, x2); C语言程序设计教程 第6章 函数与编译预处理 2021-8-444 嵌套关系: main函数root 函数f 函数 调用root函数调用xpoint函数 输出结果 xpoint 函数 调用 f 函数 调用关系: main froot fxpoint f C语言程序设计教程 第6章 函数与编译预处理 2021-8-445 函数调用它本身,称为递归。直接在函数内调用自己为直接 递归,通过别的函数调用自己为间接递归。 void a( ) . a( ); . void a( ) . b( ); . void b( ) . a(
18、 ); . 递归在解决某些问题中, 是一个十分有用的方法。 因为其一,有的问题它本 身就是递归定义的;其二, 它可以使某些看起来不 易解决的问题变得容易 解决,写出的程序较简 短。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-446 由于 n!= n*(n-1)! 是递归定义 所以求n! (n-1)! (n-1)! (n-2)! (n 2)! (n-3)! 0!的问题, 根据公式有0!=1。 再反过来依次求出1!,2!直到最后求 出n!。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-447 long fac( int n) long f; if (n=0) f=
19、1; else f=n* fac(n-1); return f; main( ) long y; int n; scanf(“%d”, y=fac(n); printf(“%d!=%ld”,n,y); 刚开始的时候,这个n是前面 输入的需要阶乘的n 所以在这里带入的值是n 而这个函数里又调用 了本身,不过参数已经 变成了n-1 所以这里再次调用时 参数已经变成了n-1 注意:上次调用fac(n) 还没有完,只是由于遇到 了fac(n-1)而执行fac(n-1) 去了. 而在调用fac(n-1)时同样 遇到了要调用fac(n-2)的 问题,于是一层一层的 包裹下去,每次调用的 时候都会在内部调用
20、一 个结构相同但变量不同 的函数,直到。 直到调用到fac(0)时, 由于内部if判断,已经 不需要再继续调用另一 个fac(n-1),而直接有了f=1 fac(0)已经执行完毕,它的 返回值被fac(1)中的f=n*fac(n-1) 语句赋给了f值,同时返回了f。 而这个返回的f又被fac(2)乘上 当前的n值以后继续返回f 直到最后的fac(n)都做完了, f的值被返回到了它的调用点: 主函数中,这样就是一个递归 运算。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-448 C语言程序设计教程 第6章 函数与编译预处理 2021-8-449 函数调用过程: main函数 输出
21、f(5) y=5*f(4) f函数,n=5 y=4*f(3) f函数,n=4 y=3*f(2) f函数,n=3 y=3*f(2)y=2*f(1) f函数,n=2 y=1 f函数,n=1 y=2y=6 y=6y=24 y=120 C语言程序设计教程 第6章 函数与编译预处理 2021-8-450 三、递归的条件: 1、须有完成函数任务的语句;long f(int n) long y; if (n=1) y=1; else y=n*f(n-1); return(y); 2、一个确定是否能避免递归调用的测试; 3、一个递归调用语句; 该语句的参数应该逐渐逼近结束条件,以至最后断绝递归。 4、先测试,
22、后递归调用。 在递归函数定义中,必须先测试,后 递归调用。也就是说,递归调用是有条件 的,满足了条件后,才可以递归。 long f(int n) long y; y=n*f(n-1); if (n=1) y=1; return(y); C语言程序设计教程 第6章 函数与编译预处理 2021-8-451 四、递归的特点: 1、递归调用不是重新复制该函数,每次调用它时,新的局部 变量和形参会在内存中重新分配内存单元,并以新的变量 重新开始执行;每次递归返回时,当前调用层的局部变量 和形参被释放,并返回上次调用自身的地方继续执行; 2、递归调用一般并不节省内存空间,因为每次调用都要产生 一组新的局部
23、变量,从而不破坏上层的局部变量; 3、递归调用一般并不能加快程序的执行速度,因为每次调用 都要保护上层局部量(现场),而返回时又要恢复上层局 部量,占用执行时间; 4、递归函数中,必须有结束递归的条件; 5、递归调用的优点是能实现一些迭代算法难以解决的问题。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-452 C语言程序设计教程 第6章 函数与编译预处理 2021-8-453 C语言程序设计教程 第6章 函数与编译预处理 2021-8-454 C语言程序设计教程 第6章 函数与编译预处理 2021-8-455 C语言程序设计教程 第6章 函数与编译预处理 2021-8-456
24、C语言程序设计教程 第6章 函数与编译预处理 2021-8-457 C语言程序设计教程 第6章 函数与编译预处理 2021-8-458 说到递归,就不能不提汉诺塔,汉诺塔是一个很繁杂的游 戏,但可以用递归的方法异常简单的完成。 规则:(1) 一次只能移动一个 (2) 大的不能放在小的上面 (3) 只能在三个位置中移动 C语言程序设计教程 第6章 函数与编译预处理 2021-8-459 对于把n个金片从第一根针a上移到第三 根针c的问题可以分解成如下步骤: (1)将n-1个金片从a经过c 移动到b。 (2)将第n个金片移动到c。 (3)再将n-1个盘子从b经过a移动到c。 这样我们就将移动n个金
25、片的问题变成了移动n-1个金片的问 题。这样做下去的话最后就会变成移动一个金片的问题。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-460 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); n=1时, 直接将金片 从a移动到c n-1个金片从a经过 c 移动到b 将第n个金片 从a移动到c再将n-1个盘子从 b经过a移动到c main( ) int n; print
26、f(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); C语言程序设计教程 第6章 函数与编译预处理 2021-8-461 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 输入3。则n=3 C语言程序设计教程 第6
27、章 函数与编译预处理 2021-8-462 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 主函数调用hanoi(n,1,2,3); 第 一 次 调 用 。 第 一 次 调 用 hanoi(n,a,b,c) (第一层) 即要把三个金片移到c n=3
28、C语言程序设计教程 第6章 函数与编译预处理 2021-8-463 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 由于n1则执行hanoi(n-1,a,c,b) (第二次调用) n=3 C语言程序设计教程 第6章 函数与编译预处理 2021-8-4
29、64 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 由于仍然n1则执行 hanoi(n-1,a,c,b) (第三次调用) n=2 C语言程序设计教程 第6章 函数与编译预处理 2021-8-465 void hanoi(int n, int a,
30、int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 由于n=1则printf(“%d -%d”,a,c); 即把金片从a移动到c n=1 C语言程序设计教程 第6章 函数与编译预处理 2021-8-466 void hanoi(int n, int a, int b, int c) if (n=1) p
31、rintf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 第三层执行完毕,返回到第二 层,即下去执行printf(“%d- %d”,a,c); 把第二个金片摆到第 二根针上 n=2 C语言程序设计教程 第6章 函数与编译预处理 2021-8-467 void hanoi(int n, int a, int b, int c) if (n=1) printf
32、(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 执行下一条语句,又调用第三 层hanoi(1,3,1,2) n=2 C语言程序设计教程 第6章 函数与编译预处理 2021-8-468 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,
33、c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); n=1, 执行结果为32 n=1 C语言程序设计教程 第6章 函数与编译预处理 2021-8-469 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main
34、( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3); 第二层也执行完了,返回第一 层,执行接下来的语句,结果 为13。 n=3 C语言程序设计教程 第6章 函数与编译预处理 2021-8-470 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”);
35、 scanf(“%d”, hanoi(n, 1, 2, 3); 执行接下来的语句,再次调用 第二层hanoi(2,2,1,3) n=3 C语言程序设计教程 第6章 函数与编译预处理 2021-8-471 void hanoi(int n, int a, int b, int c) if (n=1) printf(“%d -%d”,a,c); else hanoi(n-1,a,c,b); printf(“%d -%d”,a,c); hanoi(n-1,b,a,c); main( ) int n; printf(“input n:”); scanf(“%d”, hanoi(n, 1, 2, 3);
36、 C语言程序设计教程 第6章 函数与编译预处理 2021-8-472 编译程序会提示出错: Undefined symbol a 和 Undefined symbol b 。为什么? C语言程序设计教程 第6章 函数与编译预处理 2021-8-473 一 相关概念 一、作用域 定义:指变量能够起作用的程序范围。 如果一个变量在某源程序文件或某函数范围内有效,则称 该文件或函数为该变量的作用域。 局部变量 全局变量 从作用域角度 二、生存期 定义:指变量在内存中存在的时间范围。 静态变量 动态变量 从生存期角度 变量在整个程序的运行时间都存在 变量只在某个函数的执行过程中才存在 C语言程序设计教
37、程 第6章 函数与编译预处理 2021-8-474 二 局部变量和全局变量 (一)、局部变量 1、定义:在函数内部定义的变量 2、例: int f1(int a) int v1, x; int f2(void) int v2, x, y; main( ) int m, y; a、v1、x的有效范围 v2、x、y的有效范围 m、y的有效范围 C语言程序设计教程 第6章 函数与编译预处理 2021-8-475 3、说明: 、主函数main中定义的变量也只在主函数中有效,其它函 数不能引用; 、不同函数中可以使用相同名字的变量,它们代表不同的 对象,占用不同的内存单元,互相独立; 、形式参数也是局部
38、变量; 、可以在复合语句中定义变量,其作用域只是本复合语句。 main( ) int a, b; int c; c=a+b; c在此范围内有效a、b在此范围内有效 C语言程序设计教程 第6章 函数与编译预处理 2021-8-476 void main( ) int i,a=0; for (i=1; i=2; i+) int a=1; a+; printf(i=%d, a=%dn, i, a); printf(i=%d, a=%dn, i, a); i=1, a=2 i=2, a=2 i=3, a=0 (二)、全局变量 1、定义:在函数外部定义的变量,又称为外部变量 全局变量可以为本文件中其它函
39、数所共用,其有效范围 为:从定义变量的位置开始到本源文件结束。 eg614.cpp C语言程序设计教程 第6章 函数与编译预处理 2021-8-477 2、例: #include int p=1, q=5; float f1(int a) int b, c; char c1, c2; char f2(int x, int y) int i, j; . main( ) int m,n; 全局变量p、q的 作用域 全局变量c1、c2 的作用域 C语言程序设计教程 第6章 函数与编译预处理 2021-8-478 3、说明: 、全局变量增加了函数间的数据联系; 、尽量少使用全局变量(除非在必要时);
40、各模块间的相互联系、相互影响太多,降低了模块的独立性; 会降低程序的清晰性,因为各个函数都有可能改变全局变量的 值,需要时刻记住变量的当前值,编程时候容易出错。 #include int k; void show( ) for (k=1; k=10; k+) putchar(*); putchar(n); main( ) for (k=1; k=4; k+) show( ); eg615.cpp C语言程序设计教程 第6章 函数与编译预处理 2021-8-479 、若全局变量与局部变量同名,则在局部变量的作用范围 内,全局变量不起作用; #include int a=3, b=5; int m
41、ax(int a, int b) int c; c=ab ? a : b; return(c); void main( ) int a=8; printf(%d, max(a, b) ); 形参a、b的作用域 全局变量a、b不起作用 局部变量a的作用域 全局变量b的作用域 全局变量a不起作用 eg616.cpp C语言程序设计教程 第6章 函数与编译预处理 2021-8-480 、若全局变量在文件开头定义,则在整个程序中都可以使 用;若不在开头定义,其作用域只限于说明处到文件结 束。如果想在定义之前的函数中引用该全局变量,则在 函数中用关键字“extern”作“外部变量声明”,在函数 内部,从
42、声明之处起,可以使用它们。 #include int max(int x, int y) int z; z=xy ? x : y; return(z); void main( ) extern int a, b; printf(%d, max(a, b) ); int a=13, b=-8; eg617.cpp C语言程序设计教程 第6章 函数与编译预处理 2021-8-481 三 变量的存储类别 (一)、存储空间的划分 程序区 静态存储区 动态存储区 程序区:用于存放程序编译后形成的可执行代码 (执行时装入) 静态存储区:用于存放程序中的静态数据,如全 局变量等 动态存储区:用于存放程序中的
43、动态数据,如函 数形参、局部变量、函数调用时的现场 保护和返回地址等 静态数据说明时在静态存储区中分配存储单元并在程序执行过程中始 终占用该单元,直到程序结束才释放; 动态数据在函数开始执行时分配动态存储空间,函数结束时释放这些 空间。 的存储类别有四种:auto、static、register和extern。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-482 (二)、局部变量的存储方式 1、函数中的局部变量,如不做专门的声明,都是动态分配 存储空间的,存储在动态存储区中;用关键字auto作存 储类型的声明,这类变量称为自动变量。 auto int b, c=3; auto
44、float f; 通常auto被省略,auto不写则隐含确定为“自动存储类别” int b, c=3; float f; 2、局部静态变量 函数编译时在静态存储区分配存储单元,函数调用结束后 不释放存储单元,即在整个程序的运行中不释放存储单元。 用static声明该变量为“局部静态变量”。 static int s;static char ch; C语言程序设计教程 第6章 函数与编译预处理 2021-8-483 void f(int c) int a=0; static int b=0; a+; b+; printf(%d: a=%d, b=%dn, c, a, b); void main(
45、 ) int i; for (i=1; i=3; i+) f( i ); 1: a=1, b=1 2: a=1, b=2 3: a=1, b=3 说明: 、静态局部变量采用静态存储方式,而自动变量采用动 态存储方式; eg618.cpp C语言程序设计教程 第6章 函数与编译预处理 2021-8-484 、若对变量赋初值,对于静态变量,只执行一次,再次调 用函数时不再赋初值而保留上次函数调用结束时的值; 而对于自动变量,每次调用都要重新分配内存单元并赋 初值; 、若不对变量赋初值,对于静态变量系统自动赋缺省值; 而对于自动变量,只分配存储单元,其值不确定。 、虽然静态局部变量在函数调用结束后仍
46、占存储单元,但 由于是局部变量,其它函数不能引用它。 适用范围: 、需要保留函数上一次调用结束时的值;(占用永久性的 存储空间) 、对于数组进行初始化,通常定义为静态存储类别。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-485 3、寄存器(register)变量 为了减少从内存中存取变量值的时间,语言允许将局部 变量的值放在寄存器中;用关键字register声明。 int fac(int n) register int i, f; for (i=1; i=n; i+) f=f * i; return( f ); 说明: 、只有局部自动变量和形参可以定义为寄存器变量,关 键字r
47、egister不能省略; 、不能定义太多的寄存器变量,因为寄存器数量有限, 太多无效(将自动按自动变量处理)。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-486 (三)、全局变量的存储方式 全局变量是在函数外部定义的,存放在静态存储区,在 程序的整个运行过程中占用存储单元,生存期为整个程序的 运行期间。 全局变量有两种存储类别:static和extern,用来对其作 用域进行限制或扩充。 1、如果想在定义之前的函数中引用全局变量,则在函数中用 关键字“extern”作“外部变量声明”,在函数内部,从声 明之处起,可以使用它们。 void main( ) extern int
48、a, b; printf(%d, max(a, b) ); int a=13, b=-8; C语言程序设计教程 第6章 函数与编译预处理 2021-8-487 2、如果一个程序由多个源程序文件组成,那么一个某文件中 的函数能否引用另一个文件中的全局变量,有两种情况: 、在一个文件中要引用另一文件中定义的全局变量,要在 引用它的文件中用extern作声明。 int a; void main( ) file1.c extern int a; int power( ) file2.c 在文件file1.c中定义的变量a,在文件file2.c中引用,引 用前加上extern进行声明。 C语言程序设计教
49、程 第6章 函数与编译预处理 2021-8-488 、全局变量仅限于被本文件中的函数引用,其它文件不能 使用。定义全局变量时用static进行声明。 static int a; void main( ) file1.c extern int a; int power( ) file2.c 加上static,限制了a的作用域,在file2.c中引用失败; 但不管是否加上static,a都按静态存储方式存放。 C语言程序设计教程 第6章 函数与编译预处理 2021-8-489 四 函数的作用域和存储类别 1、内部函数 如果一个函数只能被本文件中其它函数所调用,称为内部 函数(或静态函数)。定义时在函数类型前加static。 static int fac(int x) 2、外部函数 定义时在函数类型前加关键字extern。 extern int fac(int x) 语言规定,如果在定义函数时省略extern,则隐含为外 部函数。 说明:在需要调用此函数的文件中,要用extern声明所调 用函数的原型。 C语言
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- DB54T 0495-2025 高寒草甸退化分级标准
- 二零二五年度房地产联合开发合同-文化产业园地产合作
- 2025版生物科技产业合伙投资框架协议
- 2025版特色药品代理销售合作合同
- 二零二五年脚手架租赁服务与施工协调合同
- 2025版路灯工程知识产权共享合同范本
- 2025版会议场地租赁及绿色环保设施配套合同
- 2025版瑜伽馆投资合作协议
- 二零二五年船舶燃油行业标准制定与实施合同
- 2025年度智能家居安装与维护服务合同
- TPM活动推进管理制度
- (高清版)DZT 0081-2017 自然电场法技术规程
- 《口腔基础医学概要》课件-口腔病理概要
- 中考数学几何专项练习:胡不归(解析版)
- 五年级上册语文同步课件-21古诗词三首(山居秋暝、枫桥夜泊、长相思)第二课时(人教部编版)(共36张PPT)
- 医院儿童口腔科乳牙金属预成冠修复学习培训课件
- 抖音认证承诺函
- 《精益生产培训》课件
- 大件垃圾回收技术方案
- 月球基地建设与运行管理模式
- 寿衣店创业计划书
评论
0/150
提交评论