




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第四章第四章 模块化程序设计模块化程序设计主讲人:韩维良2022年3月8日C语言程序设计C语言支持模块化程序设计的功能:(1) C语言用函数组织程序: 一个程序由一个或多个源程序文件组成; 每一个源程序文件就是一个程序模块; 每一个程序模块由一个或多个函数组成。程序设计的任务就是设计一个个函数,并且确定它们之间的调用关系。在设计函数时要使每个函数都具有各自独立的功能和明显的界面。 C语言程序设计 (2) 通过给变量定义不同的存储类别,控制模块内部及外部的信息交换。 (3) 具有编译预处理功能,为程序的调试、移植提供了方便,也支持了模块化程序设计。C语言程序设计第一节第一节 函函 数数一、设计一
2、、设计C C语言程序就是设计函数语言程序就是设计函数用C语言设计程序,任务只有一种,就是编写函数,至少也要编写一个main函数。执行C程序也就是执行相应的main函数。即从main函数的第一个前花括号开始,依次执行后面的语句,直到最后的后花括号为止。C语言程序设计模块化程序设计有一个原则模块化程序设计有一个原则:就是每个模块的规模一般不能太大(一般要控制在4060行之间),以便于阅读,便于检查其中的错误。在C语言中,减少主函数规模的一项基本措施就是通过调用其它函数来实现主函数需要的一些功能。一般一般C C语言程序的执行过程语言程序的执行过程程序结构图程序结构图大学信息管理系统C语言程序设计二、
3、函数结构二、函数结构一个C语言函数的结构形式如下:函数头函数体C语言程序设计1. 函数头函数头结构: 函数类型函数类型 函数名(形式参数表列)函数名(形式参数表列)一个函数的函数头的结构如下:(1)函数类型:指定函数值的类型,即函数返回值的类型。(2)函数名:必须采用合法的用户标识符。(3)圆括号:是“函数运算符”,表示进行函数运算,函数运算符具有很高的运算优先级别。C语言程序设计(4)形式参数表:由写在一对圆括号(函数运算符)中的一系列参数组成。每一个参数由一个类型符和一个参数名组成。参数名是合法的标识符。函数可以没有参数,这时在函数运算符内写一个“void”,也可以空白,但小括号不能省略。
4、C语言程序设计2. 函数体 函数体由一些语句组成。主要是三种类型的语句:声明语句声明语句:声明在函数中要使用的变量等程序实体。可执行语句可执行语句:用来实现函数的功能,包括若干流程控制 语句和表达式语句。returnreturn语句语句:停止本函数的执行,使流程返回到调用处。C语言程序设计编译器将函数分为三类进行处理:纯粹计算型函数,如sqrt()和sin()。将返回一个计算结果。完成一项具体工作,返回完成的成败。如printf()执行成功时,返回显示的字节数;失败时,返回一个负整数。函数不产生返回值,其类型应定义为void。C99规定,对于非void类型的函数,必须使用有返回值的return
5、语句。int absolutevalue (int x) /* 绝对值函数 */ return (x=0?x:-x); void spc (int n) /* n空格函数 */ int i;for (i=0; in;i+) printf ();return; /* 可以不要return语句 */ float y(float x) if (x10)return (2*n+3);elsereturn; C语言程序设计3. 函数中变量的作用域 作用域作用域指的是一个程序段中的变量的作用范围,在一个函数中定义的变量只在本函数中有效,在其它函数中不能使用这个变量。因此说,该变量的作用域是它所在的函数(从
6、定义该变量的行开始到函数末尾)。即使在不同的函数中定义了同名的变量,它们也是指不同的变量。#include int func(int x) x=5;return x+3;int main(void)printf(x=%dn,x);return 0;C语言程序设计 4. 空函数空函数是一个不产生任何有效操作的函数,但它却是一个合法的C函数。例如函数void null(void) 就是一个空函数。空函数多使用在模块化程序的设计或测试中。有一些函数还未编写,可用空函数进行调试,这样就可以调试程序的其它部分,等以后再逐步补上。C语言程序设计三、函数定义与函数声明三、函数定义与函数声明1、函数定义函数定
7、义是按照C语言的语法规则引入新的函数,并提供如下信息:函数的返回值类型(如果有);参数的个数及类型和名称;调用函数时要执行的代码;函数的有效性(不能嵌套定义)。C语言程序设计函数的定义函数的定义类型说明符类型说明符 函数名函数名( (类型名类型名 形式参数形式参数1 , 1 , 类型名类型名 形形式参数式参数2 , ) /2 , ) /* * 函数的首部函数的首部 * */ / 说明部分说明部分 / /* * 函数体函数体 * */ / 语句部分语句部分 C语言程序设计其中类型说明符和函数名部分共称为函数头函数头。类型说明符类型说明符即本函数的类型,实为函数返回值的类型。函数名函数名是由用户定
8、义的标识符,函数名后有一个括号,其内容为形参表。在形参表中给出的参数称为形式参数形式参数,即形式参数变量的定义,各参数定义之间用逗号间隔各参数定义之间用逗号间隔。在进行函数调用时,主调函数将赋予这些形式参数实际的值。当形参表中无参数时,括号不可少。 中的内容称为函数体函数体。在函数体中也有类型说明, 这是对函数体内部所用到的变量的类型说明。注意:函数不能嵌套定义。 void fun1() int fun2() C语言程序设计2 2、函数的返回值及其类型、函数的返回值及其类型(1 1) returnreturn语句语句函数的返回值通过函数体内的return语句实现。returnreturn 返回
9、值表达式返回值表达式 ; ;或returnreturn ( (返回值表达式返回值表达式););如果没有返回值,格式中的左、右圆括号可以省略,即写为:returnreturn ; ;功能:返回调用函数,并将“返回值表达式”的值带给调用函数。C语言程序设计说明:1)函数的返回值只能有一个。2)当函数中不需要指明返回值时,可以写成:return;也可以不写。函数运行到右花括号自然结束。3)一个函数体内可以有多个返回语句,不论执行到哪一个,函数都结束,回到主调函数。4)当函数没有指明返回值,即return; 或没有返回语句时,函数执行后实际上不是没有返回值,而是返回一个不确定的值,有可能给程序带来某种
10、意外的影响。C语言程序设计(2)函数返回值的类型函数定义时的类型就是函数返回值的类型。从理论上,C语言要求函数定义的类型应当与返回语句中表达式的类型保持一致。当两者不一致时,系统自动进行转换,将函数返回语句中表达式的类型转换为函数定义时的类型。如果定义函数缺省函数类型,则如果定义函数缺省函数类型,则系统一律按系统一律按intint型处理型处理。C语言程序设计 3、函数声明函数声明是对所用到的函数的特征进行必要的声明。编译系统以函数声明为检测依据编译系统以函数声明为检测依据:检测形参与实参类型是否一致,返回值的类型是否正确,以保证调用表达式与函数之间的参数正确传递。声明语句提供的必要信息包括声明
11、语句提供的必要信息包括:函数名,函数的类型,函数参数的个数、排列次序以及每个参数的类型。C语言程序设计函数的定义可以按任意的次序,但在主调函数中,要调用另一个函数,则需要对被调函数先做声明(或者说明)。所谓声明所谓声明,就是把函数的类型、函数的名称、函数形参的类型及个数、顺序通知编译系统,便于在调用时进行检查。函数声明的一般形式: 函数类型函数类型 函数名函数名( (参数类型参数类型1 , 1 , 参数类型参数类型2) ;2) ;或 函数类型函数类型 函数名函数名( (参数类型参数类型1 1 参数名参数名1 , 1 , 参数类型参数类型2 2 参数名参数名2) ;2) ;C语言程序设计说明:(
12、1)如果被调函数的返回值为int类型,则不管被调函数位置如何均不需要在主调函数中说明。(2) 如果被调用函数的声明放在源文件的开头,则该声明对整个源文件都有效。(3) 如果被调用函数的声明是在调用函数定义的内部,则该声明仅对该调用函数有效。 C语言程序设计(4) 在函数调用中,有下面几种情况可以省略声明:a. 如果调用函数和被调用函数是在同一个源文件中,而且被调用函数的定义是在调用函数之前。b. 函数的返回值是整数或字符。c. 所有被调用函数的声明都是在源文件开头。d. 如果被调用函数不是在源文件开头,而是在源文件中间且在所有函数之外某处被声明时,则在被声明之后引用它时,不必再声明,但在被声明
13、之前引用它时,需要对其进行声明。(5) 如果调用函数和被调用函数的定义是在同一源文件中,应该先说明或定义被调用函数。设有一函数的定义为:double func (double a, int b, char c)/* 函数体*/与之相应的函数声明应为:double func (double x, int y, char z); /* 注意末尾的分号 */3333C语言程序设计例求二实数之和main ( ) float add(float,float); float a, b, c; scanf(%f%f,&a, &b); c=add(a, b); /*函数表达式调用形式*/ printf (su
14、m= %f;c);float add( float x, float y) float z; z=x+y; return z;说明:调用过程中参数的对应关系。C语言程序设计例 定义一个求两个整数中极大值的max()函数。 /*功能:求2个整数中的较大数 */*形参:2个,整型 */*返回值: 2个整数中的较大数 */int max(int n1,int n2) /*函数定义 */ int z; z= n1 n2 ? n1 : n2; return (z);C语言程序设计void main( void ) int max(int n1, int n2); /*对被调函数说明*/ int num1
15、,num2; printf(input two numbers: ); scanf(%d%d, &num1, &num2); printf(max=%dn, max(num1, num2);C语言程序设计四、虚实结合与传值调用四、虚实结合与传值调用一个函数中的函数体,只有在该函数被调用时才会执行。在函数被调用时进行如下两个操作:将函数调用中的实际参数值传送给函数定义中的形式参数;将流程从调用处转到被调用函数的开头,开始执行函数体中的代码。C语言程序设计1 1、函数调用的一般形式、函数调用的一般形式格式: 函数名(实参表)函数按名称调用。如果是调用无参函数,则实参表可以没有,但括号不能省略。用逗
16、号分隔多个实参。实参与形参的个数应相等,类型应一致。实参与形参按顺序对应,一一传递数据。 调用时,实参必须具有确定的值,且与形参个数相等、调用时,实参必须具有确定的值,且与形参个数相等、类型匹配。类型匹配。C语言程序设计(1 1)形参与实参)形参与实参形式参数形式参数:定义函数时函数名后面括号中的变量名:定义函数时函数名后面括号中的变量名实际参数实际参数:调用函数时函数名后面括号中的表达式:调用函数时函数名后面括号中的表达式开参是虚的,类似于占位符,而实参是实的,具体的。形参出现在函数定义中,只能在该函数体内表示欲处理的数据,并没有确定的值。发生函数调用时,调用函数把实参的值传送给被调用函数中
17、的形参,从而实现调用函数向被调用函数的数据传送。C语言程序设计(2 2)函数调用的方式)函数调用的方式按函数在程序中出现的位置分,有2种函数调用方式。1) 1) 函数语句函数语句函数语句的调用,是指把被调函数作为一个独立的语句直接出现在主调函数中。2) 2) 函数表达式函数表达式被调函数出现在主调函数中的表达式中,这种表达式称为函数表达式。在被调函数中,必须有一个函数返回值,返回主调函数以参加表达式的运算。 C语言程序设计(3 3)说明)说明1)按函数名调用函数。2)实参在类型上按顺序与形参一一对应和匹配实参在类型上按顺序与形参一一对应和匹配。如果类型不匹配,C编译程序将按赋值兼容的规则进行转
18、换。如果实参和形参的类型不赋值兼容,通常并不给出出错信息,且程序仍然继续执行,只是得不到正确的结果。3)实参可以是常量、变量、表达式、函数等实参可以是常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此,应预先用赋值、输入等办法,使实参获得确定的值。C语言程序设计4)形参变量只有在被调用时,才分配内存单元;调用结束时,即刻释放所分配的内存单元。因此,形参只有在该函数内有效。调用结束,返回调用函数后,则不能再使用该形参变量。5)实参对形参的数据传送是单向的实参对形参的数据传送是单向的,即只能把实参的值传送给形参,而不能把形参的
19、值反向地传送给实参。6)实参和形参占用不同的内存单元,即使同名也互不影响。2 2、函数调用时的虚实结合、函数调用时的虚实结合参数是函数调用时进行信息交换的载体。实参是调用函数中的变量,形参是被调函数中的变量。函数调用时实现了实参与形参的结合。这称为“虚实结合”。#include float add( );int main(void)float x=1.5, y=-5.7;printf (%f+%f=%fn, x,y, add(x,y);float add (unsigned int a, unsigned int b) printf(a=%u, b=%un, a,b);return (a+b)
20、;3 3、传值调用的虚实结合过程、传值调用的虚实结合过程程序进行编译时,并不为形式参数分配存储空间。只有在被调用时,形式参数才临时地占有存储空间,其过程如下:(1)调用开始,系统为形参开辟一个临时存储区,形参与实参各占一个独立的存储空间。(2)将各实参之值传递给对应形参,形参得到了实参的值。这种虚实结合方式称为“值结合”。(3)函数返回时,临时存储区也被撤销。特别注意:在C程序中实参与形参是传值调用(call by value) 的特点。即实参与形参是“单向的值传递单向的值传递”即函数中对形参变量的操作不会影响到调用函数中的实参变量,即形参值不能传回给实参。#include void swap
21、 (int x, int y);int main(void)int a=3, b=5;swap (a,b);printf (a=%d, b=%dn, a,b);return 0;void swap (int x, int y)int temp;temp=x, x=y, y=temp; /* 交换变量的值 */printf(x=%d,y=%dn,x,y);执行结果:执行结果:x=5,y=3a=3,b=5企图交换变量企图交换变量a,b的值,没的值,没有成功有成功五、五、函数的嵌套调用函数的嵌套调用语言的函数定义是互相平行、独立的函数不能嵌套定义可以嵌套调用函数调用一个函数的过程中,又可以调用另一个
22、函数。函数的嵌套调用函数的嵌套调用的过程的过程main函数函数调用调用a函数函数结束结束a函数函数调用调用b函数函数b函数函数C语言程序设计例一个偶数为两个素数之和。德国数学家哥德巴赫(GoLdbach)在1725年写给欧拉(Euler)的信中写下了以下猜想:任何不小于6的偶数都是两个素数之和(俗称为1+1)。如633,1257等等。 两个多世纪过去了,这一猜想既无法证明也没被推翻。试设计程序验证这一猜想是否成立。 对于一个偶数,找出一个小于它的数,判断是否是素对于一个偶数,找出一个小于它的数,判断是否是素数数,如果是就计算该偶数与该素数的差并判断它是否是素数。如果两者都是素数则猜想得到验证。
23、问题表现为:任意输入一个偶数,可将其分解为两个素数之和。5050C语言程序设计#include main()void even(int x);int a;printf(“请输入一个偶数:”);scanf(“%d”,&a);if (a%2=0) even(a); /*函数调用语句*/else printf(“所输入的数不是偶数!n”);5151C语言程序设计void even(int x)int isprime(int a);int i;for(i=2;i=x/2;i+) if ( isprime(i) & isprime(x-i) ) printf(“%d=%d+%dn”,x,i,x-i);
24、return; C语言程序设计int isprime(int a)int i;for(i=2;i=a/2;i+) if(a%i=0) return 0;return 1; 注意两个返回语句。C语言程序设计例输入一个由若干个单词组成的文本串,每个单词之间用空格、换行符、跳格符(制表符)分隔,且分隔符可以不至一个(如连续的两个空格),以作为输入的结束标志,统计此文本串单词的个数? 如输入:T This i is a a s student.分析:,所以从输入的文本串中逐个读取每一个字符,当读到每一个单词的第一个字母时,计数器加1 。如何知道读取到的字符是单词的第一个字母呢?如何知道读取到的字符是单
25、词的第一个字母呢?如果读取到的字符是分隔符,则不是单词的一部分;如果读取到的字符不是分隔符,且它的上一个字符是分隔符,则它是单词的第一个字母,计数器加1。如果读取到的字符不是分隔符,且它的上一个字符也不是分隔符,则它是单词的非首字母,计数器不加1。C语言程序设计当前读取到的字符是否是单词的一部分,可用一个状态变量来表示,如果是单词的一部分,则用1表示,反之用0表示。#include #define IN 1#define OUT 0int countword();main()int n;n=countword();printf(“单词数为:%dn”,n);5555C语言程序设计int coun
26、tword() /*没有形参*/int c,nw,state;state=OUT;nw=0;while(c=getchar()!=)if(c= |c=n|c=t) state=OUT;else if(state=OUT) state=IN; nw+; return(nw);六、递归函数六、递归函数一个函数可以调用另一个函数。递归函数一个函数自己调用自己(直接地或间接地调用自己)。前者称为直接递归调用函数,后者称为间接递归调用函数。 1.递归调用次数有限 2.程序执行有规律 3.有结束调用的条件C语言程序设计递归调用是指一个函数直接或间接地调用自己。这种函数称为递归函数。自己调用自己自己调用自己
27、,即要解决一个问题,转化为一个用同样的方法解决的新问题,只是参数在不断地递增或者递减。在递归调用中,主调函数又是被调函数。执行递归函数将反复调用其自身。 对于一些特定的问题,用递归算法来解决,可以简化问题的复杂程度。3/8/2022583/8/202259C语言程序设计例:用递归调用求n!。要用递归法解决此问题,必须明确两个问题:、递归算法n!=n*(n-1)!(n-1)!=(n-1)*(n-2)!;求n的阶乘的问题,转化为用同样的方法求(n-1)的阶乘。如:4!4*3! 3!3*2!如果编写成一个函数,则调用如下:f(n)=n*f(n-1);不断地自己调用自己。C语言程序设计、递归终结条件递
28、归到一定的程度后,必须终止。如求阶乘时,当求到1!时,必须停止递归。f(1)=1这一条是必须的,否则将会没完没了的进行下去。通常用条件判断, 满足某种条件后就不再作递归调用,然后逐层返回。C语言程序设计例如有函数f如下:int f(int x) z=f(x1); return z;上页中的函数是一个递归函数。 但是运行该函数将无休止地调用其自身,这当然是不正确的。为了防止递归调用无终止地进行, 必须在函数内有终止递归调用的手段。C语言程序设计例 用递归法计算n!。#include long f(int n) long y; if(n1) y=n*f(n-1); else y=1; return
29、(y);6464C语言程序设计main() int n; long y; printf(“input a inteager number:”); scanf(%d,&n); y=f(n); printf(%d!=%ldn,n,y);程序运行情况如下:input a inteager number: 5 5!=120C语言程序设计程序说明:程序中给出的函数f是一个递归函数。主函数调用f 后即进入函数f执行,如果n0,n=0或n=1时都将结束函数的执行,否则就递归调用f函数自身。由于每次递归调用的实参为n-1,即把n-1 的值赋予形参n,最后当n-1的值为1时再作递归调用,形参n的值也为1,将使递
30、归终止。然后可逐层退回。C语言程序设计如求4!的过程分解如下:f(4)=4*f(3)f(3)=3*f(2)f(2)=2*f(1)f(1)=1f(4)=4*6=24f(3)=3*2=6f(2)=2*1=2C语言程序设计例:用递归法求菲波那契数列第40项的值,该数列为:1,1,2,3,5,8,13,21,规律:每一项为其前两项的和。递归算法如下:fib(n)=fib(n-1)+fib(n-2);递归的终结条件如下:fib(1)=1;fib(2)=1;C语言程序设计#include main()int n;long fib(int); /*第40项的值很大*/printf(“请输入项数:”);sca
31、nf(“%d”,&n);printf(“第%d项的值为:%ldn”,n,fib(n);6969C语言程序设计long fib(int n)long result;if(n=1|n=2) result=1;else result=fib(n-1)+fib(n-2);return result;第二节第二节 变量的存储属性变量的存储属性变量是对程序中数据存储的抽象。C语言程序中变量都有类型,数据类型是变量的运算属性的抽象,决定了该变量的取值范围和可以施加的运算种类。除此之外,变量还有一些属性,例如:一个变量在程序的哪个范围内是可以使用的变量的变量的可用域可用域; 它什么时候生成以及什么时候被撤消变
32、量的生存变量的生存期期; 它存储在什么哪种类型的存储器中以及用什么机制进行存储变量的存储区变量的存储区。这些都称为变量的存储属性。一、变量的作用域与生存期一、变量的作用域与生存期在函数中形参变量只在被调用期间才分配内存单元,调用结束立即释放。形参变量只有在函数内才是有效的,离开该函数就不能再使用了。如:货币的使用范围,校园卡的使用范围。1. 1. 局部变量和全局变量局部变量和全局变量变量的可用域是指一个变量在程序的哪个域内才是可以被识别的,也称为可见(或可用)的。变量可分为两种:全局可用全局可用全局变量全局变量局部可用局部可用局部变量局部变量。C语言程序设计局部变量局部变量:在一个函数在一个函
33、数或者复合语句或者复合语句( (如函数体、循环如函数体、循环体体) )内部内部定义定义的变量是的变量是局部变量局部变量,它只在该函数它只在该函数或者复合语或者复合语句句范围内有效。范围内有效。而在其它函数内不能使用。而在其它函数内不能使用。只有在包含变量定义的函数内部,才能使用被定义的变量,在此函数之外就不能使用这些变量了。又称为内部变量。例如:int f1(int a) /*函数f1*/ int b,c; /*a,b,c作用域:仅限于函数f1()中*/C语言程序设计int f2(int x) /*函数f2*/ int y,z; /*x,y,z作用域:仅限于函数f2()中*/ main() i
34、nt m,n; /*m,n作用域:仅限于函数main()中*/由于局部变量只在一个局部范围中使用,因此在不同的函数中可以定义同名的局部变量,它们互不干扰,各自分配不同的独立存贮单元。这种特性便于进行模块化设计,不同的模块由不同的程序员设计,各模块中使用的变量名由用户自己确定,即便相同也不会彼此影响。7575C语言程序设计#include main() void fun1(); void fun2(); int x=1; printf(“x=%dn”,x); int x=3; printf(“x=%dn”,x); printf(“x=%dn”,x); fun1(); printf(“x=%dn”
35、,x); fun2(); printf(“x=%dn”,x); fun1();C语言程序设计fun1() int x=5; printf(“x=%dn”,x); fun2() int x=7; printf(“x=%dn”,x); 说明:四个X分别分配了不同的存贮单元。同一函数的两次调用分配了不同的单元。b b的作用域的作用域C语言程序设计全局变量全局变量:也称为外部变量,是在函数外部定义的变量,作用域为从定义全局变量位置开始到源程序结束,是多个是多个函数间进行数据传递的一种手段函数间进行数据传递的一种手段。全局变量可以在其作用范围内,由各函数所共用。 在函数中使用全局变量,一般应作全局变量说
36、明。 只有在函数内经过说明的全局变量才能使用。全局变量的说明符为extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。C语言程序设计例如:int a,b; /*外部变量*/void f1() /*函数f1*/float x,y; /*外部变量*/ int f2() /*函数f2*/C语言程序设计main() /*主函数*/ /*全局变量x,y作用域 全局变量a,b作用域*/从上例可以看出a、b、x、y 都是在函数外部定义的外部变量,都是全局变量。但x,y 定义在函数f1之后,而在f1内又无对x,y的说明,所以它们在f1内无效。 a,b定义在源程序最前面,因此在f1,f2
37、及main内不加说明也可使用。8181C语言程序设计#include int a=3,b=5;main() void fun(); printf(“a=%d,b=%dn”,a,b); fun(); printf(“a=%d,b=%dn”,a,b); void fun() int c; c=a;a=b;b=c; printf(“a=%d,b=%dn”,a,b); C语言程序设计【例】输入长方体的长宽高l,w,h。求体积及三个面x*y,x*z,y*z的面积。int s1,s2,s3;int vs( int a,int b,int c)int v;v=a*b*c;s1=a*b;s2=b*c;s3=a
38、*c;return v;C语言程序设计main()int v,l,w,h;printf(ninput length,width and height: );scanf(%d%d%d,&l,&w,&h);v=vs(l,w,h);printf(v=%d s1=%d s2=%d s3=%dn,v,s1,s2,s3);程序运行结果如下:input length,width and height:4 5 6 v=120 s1=20 s2=30 s3=24C语言程序设计程序说明:本程序中定义了三个外部变量s1,s2,s3,用来存放三个面积,其作用域为整个程序。函数vs用来求正方体体积和三个面积,函数的返回
39、值为体积v。由主函数完成长宽高的输入及结果输出。由于语言规定函数返回值只有一个,当需要增加函数的返回数据时,用外部变量是一种很好的方式。本例中,如不使用外部变量,在主函数中就不可能取得v,s1,s2,s3四个值。而采用了外部变量,在函数vs中求得的s1,s2,s3值在main中仍然有效。因此外部变量是实现函数之间数据传输的有效手段。C语言程序设计当在函数外定义了一个全局变量后,定义点之后的函数都可以使用该变量.当全局变量的值在一个函数中改变后,另一个函数使用的就是改变后的值.从定义开始到程序结束,全局变量自始至终占用存储空间.全局变量的使用使函数间的联系加强,与程序设计”低耦合”的原则相违背,
40、所以很少使用。例同名局部变量例同名局部变量#include int main(void) int a=3; printf(a1=%d,a); int a=5; printf(a2=%d,a); return 0;例演示全局变量例演示全局变量#include void a() int a=1; printf(a1=%dn,a); printf(x1=%dn,x);int x=3; * 定义外部变量定义外部变量 */void b() printf(x2=%dn,x);int main(void) a(); b(); printf(x3=%dn,x); return 0;例演示全局变量与局部变量同名
41、例演示全局变量与局部变量同名#include int x=3; /* 定义外部变量定义外部变量 */int main(void) int x=5; printf(x=%dn,x); return 0;2. 2. 动态变量与静态变量动态变量与静态变量运行中的程序,在内存中被分成代码区和数据区两大部分。数据区又分为静态存储区静态存储区、自动存储区自动存储区和动态分配区动态分配区三部分。自动存储区是按栈组织的存储区。除特别声明的外,局部变量局部变量通常被存放在栈区。这些变量在进入所在的块时被创建,所在的块结束时被撤销,其值不再保留。并且,变量必须有程序员显式地变量必须有程序员显式地进行初始化进行初始
42、化,否则它们的初始值是不确定的。静态存储区静态存储区是在程序编译时就分配的存储区。分配在静态存储区的变量在程序开始执行时被创建并自动初始化(数值变量被初始化为0),当程序结束时才被撤销。所以常称静态变量的生存期是永久的静态变量的生存期是永久的。全局变量就是被分配在静态存储区的。/* 企图交换两个变量的值*/#include void swap(void);/* 说明函数 */int a=3, b=5;/* 声明外部变量 */int main(void) printf (a=%d, b=%dn,a, b); swap(); printf (a=%d, b=%dn, a,b); return 0;
43、void swap(void) int c;/* 声明自动变量*/ c=a; a=b; b=c;/* 交换变量的值 */二、二、C C语言中变量的存储类型语言中变量的存储类型根据可用域和生存期,变量有4种存储类型:局部自动类型局部自动类型,在函数内部用标识符auto或register声明。静态局部类型静态局部类型,在函数内部,使用static声明。静态全局类型静态全局类型,在函数外部,使用static声明,也称静态外部变量。全局类型全局类型,不需要标识符声明。在函数外部直接声明即可,通称外部变量。1 1、autoauto存储类型和存储类型和registerregister存储类型存储类型使用a
44、uto声明的变量是局部变量,编译器将其分配在自动存储区。其格式为:auto 数据类型变量名=初值表达式,;其中方括号表示可省略,省略auto,系统隐含认为此变量为auto。函数的参数(形参)也是一种自动变量。C语言程序设计自动变量的类型说明符为auto;语言规定,函数内凡未加存储类型说明的变量均视为函数内凡未加存储类型说明的变量均视为自动变量,也就是说自动变量可省去说明符自动变量,也就是说自动变量可省去说明符autoauto。在前面所学的程序中定义的变量凡未加存储类型说明符的都是自动变量。C语言程序设计例如: int a,b,k; char c;等价于: auto int a,b,k; aut
45、o char c;C语言程序设计自动变量自动变量的的特点:特点:自动变量的作用域仅限于定义该变量的函数或复合语句内。自动变量存贮在自动存贮区,只有在使用它,即定义该变量的函数被调用时才给它分配存储单元,开始它的生存期。函数调用结束,释放存储单元,结束生存期。因此函数调用结束之后,自动变量的值不能保留。未初始化时,自动变量的值是不确定的。未初始化时,自动变量的值是不确定的。由于自动变量的作用域和生存期都局限于定义它的函数或复合语句内,因此不同的函数中允许使用同名的变量而不会混淆。C语言程序设计寄存器变量的说明符是寄存器变量的说明符是registerregister。存放在CPU的寄存器中,使用时
46、,不需要访问内存,而直接从寄存器中读写, 这样可提高访问效率。特点:加快运算速度,函数运行完即消失、使用有限。如定义一个频繁使用的变量为寄存器类型:register int i;C语言程序设计2 2、静态局部类型、静态局部类型类型说明符:类型说明符:staticstatic,属于静态存储方式;在一个函数内部,可以用static定义一个变量,称为静静态局部变量态局部变量。其作用域仍在定义它的函数内部,但其生存期却程序运行期。函数调用结束后,并不释放所占用的存贮空间(总是占用固定的存贮空间),在程序运行期间,始终存在,但除了定义它的函数以外,别的函数不能使用。整个程序运行结束后,才释放占用的空间。
47、C语言程序设计静态局部变量的特点:静态局部变量的特点:(1)静态局部变量在每次调用函数结束后能够保留调用结束后的值不变,留待下一次调用,变量值具有继承性继承性。 (2)静态局部变量只限于被本函数使用,不能被其他函数使用 (3)静态局部变量属于静态存储类别,在整个程序运行期间都不释放;而动态存储变量属于动态存储类别,函数调用结束即释放,再次调用又将重新分配空间。(4)在定义静态局部变量时,如果不赋初值不赋初值,系统自动赋值为0或空字符(对字符型变量)。 9999C语言程序设计#include func() static int b=10; b=b+2; return b;main() int i
48、; for(i=1;i4;i+) printf(“%d,b=%dn”,i,func();#include void increment(void);int main(void)increment ( );increment ( );increment ( );return 0;void increment(void)int x=0; /*auto*/x+;printf (%dn,x);#include void increment(void);int main(void)increment ( );increment ( );increment ( );return 0;void increm
49、ent(void)static int x=0; /*使用了static说明符 */x+;printf (%dn,x);3 3、静态全局类型、静态全局类型在多文件程序中,用用staticstatic声明外部变量声明外部变量,使该外部,使该外部变量的作用域仅限于所在的文件变量的作用域仅限于所在的文件,而不用而不用staticstatic声明的外声明的外部变量的作用域为整个程序。部变量的作用域为整个程序。例如:某个程序中要用到大量函数,而有几个函数需要共同使用几个全局变量时,可以将这几个函数组织在一个文件中,而将这几个全局变量用static定义为静态的,以保证它们不会与其他文件中的变量发生名字冲突
50、,保证文件的独立性。static unsigned int r;int random(void) r=(r*123+59)%65536; return(r); /*产生r的初值*/unsigned randomstart(unsigned int seed)r=seed; #include int main(void) int i, n; printf (please enter the seed:); scanf(%d, &n); randomstart(n); for(i=1; i10; i+) printf(%u , random(); return 0; C语言程序设计4 4、外部变量
51、的定义与声明、外部变量的定义与声明外部变量的类型说明符为外部变量的类型说明符为externextern。外部变量的特点:外部变量的特点:(1) 外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变量是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。(2)当一个源程序由若干个源文件组成时, 在一个源文件中定义的外部变量在其它的源文件中也有效。一个变量被定义点之前的函数使用或者被别的文件中的一个变量被定义点之前的函数使用或者被别的文件中的函数使用时,应用函数使用时,应用externextern声明。声明。对外部变量(静态全局变量除外),除可以定义一次外,还可以多次进行声
52、明(引用性声明)。(1)通过声明将外部变量的作用域在本文件范围内扩充向前引用通常,一个外部变量的作用域是从其定义点到本文件末尾。对于位于定义点之前的函数,可以用extern声明使变量的作用域扩充到需要用到它的函数。#include void gx(), gy ();void main(void) extern int x,y; /*声明声明x,y是外部变量,作用域扩充至此是外部变量,作用域扩充至此*/ printf (1:x=%dt y=%dn, x, y); y=246; gx(); gy(); void gx() extern int x, y; /*声明声明x,y是外部变量是外部变量*/
53、 x=135; printf(2:x=%dt y=%dn, x, y);int x, y; /*定义定义x,y是外部变量是外部变量 */void gy() printf(3:x=%dt y=%dn, x, y);(2)利用声明语句将作用域扩大到其他文件建立对象的外部链接假设一个程序由两个以上的文件组成。当一个全局变量定义在文件file1中时,在另外的文件中使用extern声明,可以通知编译系统一个信息:“此变量到外部去找”。或者说在链接时,告诉链接器:“到别的文件中找这个变量的定义”。* file1.c */#include int x, y; char ch;void main(void)
54、x=12; y=24; f1(); printf(%cn, ch);* file2.c */extern int x,y; extern char ch; f1( ) printf (%d, %dn, x,y); ch=a; (3) 全局变量的副作用如果没有外部变量,函数只能通过参数与外界发生数据联系,有了外部变量以后,增加了一条与外界传递数据的渠道,但也会产生一些副作用. /* 例能否输出5行 *?*/#include int i; void main(void) void prt(); for(i=0; i5; i+) /* 输出5行 */ prt();void prt() /* 输出一行
55、5个* */ for(i=0; i5; i+) printf (%c, *); printf(n);三、通过const声明将变量存储在只读区C语言可以开辟一个只读区。数据是以变量形式存储的,只读的,不可修改。也就是把变量定义为只读变量。定义只读变量的方法是在声明变量时使用修饰符const。格式为:const 数据类型 变量1=初始表达式1,变量2=初始表达式2,如:const double X=3.14159265;C语言程序设计第三节第三节 模块的编译与链接模块的编译与链接一、分别编译一、分别编译 C语言是一种支持模块化程序设计的语言,它允许将一个大型程序分成多个程序文件分别进行编译。这样的
56、好处在于:当程序的一个局部有错误或对局部进行了修改时,可以只重新编译该局部,不需要将整个程序都重新编译。 某些经过考验的函数的目标代码可以添加为的库函数,供其他程序中使用。C语言程序设计二、用项目管理多文件程序的编译与链接过程二、用项目管理多文件程序的编译与链接过程多文件程序的编译、链接过程是比较麻烦的。为了方便用户进行多文件程序的编译、链接,各种程序开发软件都提供了用项目(project)管理多文件程序的编译和链接过程。其使用方法因开发工具而异,请参考有关手册。C语言程序设计三、头文件三、头文件用户显式地保证程序一致性的基本方法是保持声明的一致性。保持声明一致性的简单办法是提供一个头文件,让
57、头文件中的信息作为各模块之间的接口信息,有利于提供可重用的模块。使用头文件将把程序分为程序头和程序体两部分。好的头文件应包含如下一些内容:类型定义如定义一个枚举类型:enum color RED,BLUE,GREEN,YELLOW;函数声明如: extern int strlen const char*;嵌入函数声明如:inline char get() return *p+;数据声明如:extern int a;常量定义如: const float pi=3.141593;包含指令如: #include 宏定义如:#define case break; case注释好的头文件不能包含以下内容
58、:一般函数定义数据定义 如: int a;常量聚集定义 如: const tbl=/* */;用户头文件是由用户自己定义的头文件。系统将用双引号方式进行搜索。#include 头文件名.h程序员可以用它们建立各文件之间的信息窗口。应当注意,修改了头文件时,所有涉及该头文件的程序都应重新编译,所以在编制头文件时应尽量考虑周全。当使用很多头文件时,常有重复嵌入的情形发生,在这种情形下,应防止标识符重复定义的错误。为避免错误,应使用条件编译来测试有无重复定义。C语言程序设计第四节第四节 宏定义与宏替换宏定义与宏替换编译预处理是以“#”开头的一些命令,它通知编译系统:在进行正式编译前应当先进行一些前期
59、工作(即编译预处理)。目前,C语言的编译预处理功能主要有如下一些:(1)文件包含,使用命令:#include。(2)宏定义,使用命令:#define、#undef。(3)条件编译,使用命令:#if、#ifdef、#ifndef、#else、#endif、#elif、defind。(4)提供行号信息,使用命令:#line。(5)编译杂注,使用命令:#progma。(6)错误信息,使用命令:#error。在这些编译预处理中,应用最多的就是对宏的处理。它允许程序员使用define定义并应用宏名字书写C语言程序,同时也指示编译器在正式编译前通过宏替换,使程序能按照C语言的语法进行编译。一、字符串宏定义
60、及其基本格式一、字符串宏定义及其基本格式define命令最简单的应用就是定义一个符号常量。格式为: define 宏名 字符串编译预处理时,预处理程序将把程序文件中在该宏定义之后的所有宏名,用#define命令中定义的字符串(称为宏体)替换,这个过程称为宏替换。符号常数的定义就是这种宏定义的一种应用。#define PI 3.14159265#define RADIUS 2.0使用宏定义的好处是:(1) 提高了程序的可读性。如果人们看到以下语句 return (2.0*3.1415926536*2.0); 和 return (3.1415926536*2.0*2.0);是否能很快地看出它们在计
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年计算机一级Photoshop设计技术提升试题及答案
- 2025年新能源汽车充电站布局与充电服务市场细分领域研究报告
- 2025年税法知识框架梳理试题及答案
- 2025机械设备租赁合同模板2
- 商业决策中数字化的运用及领导力的作用
- 2025年农村小土地买卖合同样本
- 2025年葡萄酒产区特色品牌国际化市场渠道优化与品牌管理研究报告
- 无动力乐园项目运营模式分析:盈利模式与运营策略
- 城市公园项目环境影响评估与应对策略
- 2025著作权转让合同范本格式
- 水利工程项目预算管理方案
- 银行大额存单业务培训
- wps计算机二级试题及答案
- 师德师风-做“四有”好老师
- 衣食住行见证改革开放时代变迁-(修订)
- 弱电智能化施工方案
- TQGCML 3946-2024 柴油发电机组维护保养规范
- 输变电工程质量通病防治手册
- 新生儿X线检查
- 2024年江西省中考生物·地理合卷试卷真题(含答案逐题解析)
- 【暑假衔接】知识点专题13 写话 (讲义+试题) 二升三年级语文(含答案)部编版
评论
0/150
提交评论