函数与编译预处理_第1页
函数与编译预处理_第2页
函数与编译预处理_第3页
函数与编译预处理_第4页
函数与编译预处理_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

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

文档简介

第六章函数与编译预处理

6.1模块化程序设计与函数6.2函数的定义与调用6.3函数的递归调用6.4变量作用域与存储方式

6.5编译预处理6.6函数设计举例

C语言程序设计

函数与编译预处理

C语言程序设计

函数与编译预处理

模块化程序设计求解较小问题的算法和程序称作“功能模块”。基本思想:将一个大的程序按功能分割成一些小模块特点:各模块相对独立、功能单一、结构清晰、接口简单控制了程序设计的复杂性提高元件的可靠性缩短开发周期避免程序开发的重复劳动易于维护和功能扩充开发方法:自上向下,逐步分解,分而治之6.1模块化程序设计与函数

C语言程序设计

函数与编译预处理模块与函数

C语言程序由基本语句和函数组成,每个函数可完成相对独立的任务,依一定的规则调用这些函数,就组成了解决某个特定问题的程序。把大任务分解成若干功能模块,用多个函数来实现这些功能模块。通过函数的调用来实现完成大任务的全部功能。任务、模块与函数的关系:

一个大任务分成多个功能模块,功能模块则由一个或多函数实现。模块化的程序设计是靠设计函数和调用函数实现的。

C语言程序设计

函数与编译预处理例ex1.c:分数排序任务:输入三个数,从大到小的顺序的输出。如果大于等于85,在该数后面输出‘A’,

小于85且大于等于70,则输出‘B’,

小于70且大于等于60,输出‘C’,

如果小于60,则输出‘D’。思路:输入分数

排序

判断并输出等级

C语言程序设计

函数与编译预处理

voidsortabc(floata,floatb,floatc){floatt;

if(a<b){t=a;a=b;b=t;}/*交换a,和b的值*/

if(b<c){t=b;b=c;c=t;}/*交换b,和c的值*/

if(a<b){t=a;a=b;b=t;}/*交换a,和b的值*/}

scanf("%f,%f,%f",&a,&b,&c);

C语言程序设计

函数与编译预处理(1)/*输入*/(2)/*排序*/

chargrade(floatx){if(x>=85)

return('A');

elseif(x>=70)

return('B');else

if(x>=60)

return('C');else

return('D');

}(3)/*判断并输出等级*/

C语言程序设计

函数与编译预处理/*根据x的值,得到等级标准*//*判别等级并输出*/

voidputabc(floata,floatb,floatc){charg;g=grade(a);

printf("%6.1f:%c",a,g);g=grade(b);

printf("%6.1f:%c",b,g);g=grade(c);

printf("%6.1f:%c",c,g);}

voidmain(){floata,b,c;

scanf("%f,%f,%f",&a,&b,&c);/*输入*/

sortabc(a,b,c);/*排序*/

putabc(a,b,c);/*分等级并输出a,b,c三个数*/}

C语言程序设计

函数与编译预处理/*主函数*/模块设计的原则模块独立规模适当层次分明功能专一

C语言程序设计

函数与编译预处理独立性原则表现在模块完成独立的功能,和其它模块间的关系简单,各模块可以单独调试。修改某一模块,不会造成整个程序的混乱。每个模块完成一个相对独立的特定子功能。在对任务逐步分解时,要注意对问题的综合。例如,一些模块的相似的子任务,可以把它们综合起来考虑,找出它们的共性,把它们做成一个完成特定任务的单独模块。每个模块有特定功能1、模块独立

C语言程序设计

函数与编译预处理模块之间最好只通过数据传递发生联系,而不发生控制联系。例如,C语言禁止goto语句作用到另一个函数,就是为了保证函数的独立性。每个模块力求简单模块内使用的数据,对于不需要这些数据的其它模块来说,应该不允许使用;在一个模块内的变量的修改不会影响其它模块的数据。即模块的私有数据只属于这个模块。C语言的局部变量,就是满足模块独立的的需要。每个模块应用独立变量

C语言程序设计

函数与编译预处理

模块不能太大,但也不能太小。模块的功能复杂,可读性就不好,而且也违背独立性原则。但如果做得太小,实际上也会复杂各个模块间反复调用,可读性也会降低。这点需要慢慢积累经验,好好把握。2、规模适当3、层次分明要多层次的分解任务,注意对问题进行抽象化

C语言程序设计

函数与编译预处理算法简介什么是算法?通俗地说,算法是解决一类特定问题的方法和步骤。算法是一个有限操作的序列。算法的每一步都是确定的。算法的每一步计算机都能操作。有一个或多个的输入或输出。

C语言程序设计

函数与编译预处理6.2函数的定义与调用

在C语言中,函数(Function)是一个处理过程,可以进行数值运算、信息处理、控制决策,即一段程序的工作放在函数中进行,函数结束时可以携带或不带处理结果。从用户使用函数的角度,函数有两种:

库函数(标准函数):系统提供

自定义函数:用户自己写

从函数的形式看,函数分两类:

无参函数、有参函数

注:C语言程序处理过程全部都是以函数形式出现,最简单的程序至少也有一个main函数。函数必须先定义和声明后才能调用。

C语言程序设计

函数与编译预处理标准库函数

C语言有丰富的库函数,按功能分为:类型转换函数、字符判别与转换函数、字符串处理函数、标准I/O函数、文件管理函数、数学运算函数,这些函数的说明在不同的头文件(*.h)中。想要调用标准的库函数,就必须include。

main()

{{putchar(‘a’);}

}

C语言程序设计

函数与编译预处理调用putchar函数时,

必须include<stdio.h>#include<stdio.h>

C语言程序设计

函数与编译预处理一般格式合法标识符函数类型函数名(形参类型说明表){

说明部分 语句部分}函数的定义把完成一个子任务程序写成一个函数函数返回值类型缺省int型无返回值void函数体

C语言程序设计

函数与编译预处理intmax(intx1,intx2,intx3)/*定义函数的返回值类型,函数名,形参*/{intmax;if(x1>x2)max=x1;elsemax=x2;if(max<x3)max=x3;/*通过比较得到三个数的最大值放到max中*/

return(max);/*返回运算结果*/} 【例】编写函数,求三个整型参数的最大值。

函数分为两大部分:1.函数的说明部分(函数首部)。2.函数体部分。

C语言程序设计

函数与编译预处理1.函数的说明部分

函数的说明部分包括函数的类型、函数名、参数表及参数类型的说明。(1)函数的类型。函数的类型即函数的返回值类型。说明函数将给调用者提供什么类型的返回值。如果函数不提供返回值,可以定义函数类型为空。空类型的标识符:void

例:voidputdata(inta)函数的返回值可以是任何一种数据类型,但不能是数组型。当返回值类型被省略时,默认为int型。函数的返回值将由return(表达式)语句返回给调用者(即调用这个函数的另一个函数),表达式的值即是函数的返回值。(2)函数名函数又称为函数标识符。对自定义函数,其命名遵循C语言标识符的规定。(3)参数表参数表写在函数后的括号“()”内,参数表由一个或多个变量标识符及类型标识符组成。参数表中的变量也称为形式参数,简称为形参。如果没有形参,称作无参数函数,无参数函数的括号“()”不能省略。例有参函数

intmax(intx,inty){intz;z=x>y?x:y;return(z);}例有参函数

intmax(intx,y){intz;z=x>y?x:y;return(z);}例无参函数

printstar(){printf(“**********\n”);}或

printstar(void){printf(“**********\n”);}

C语言程序设计

函数与编译预处理2.函数体

函数定义的花括号“{}”里的部分是函数体,包括变量定义、执行语句序列。函数所完成的工作在函数体中由一段程序完成。

例空函数

dummy(){}函数体为空如果函数有返回值,则需要返回语句return.

C语言程序设计

函数与编译预处理函数的返回值返回语句形式:return(表达式);

或:

return表达式;

或:

return;执行时先计算出括号中表达式的值,再将该值返回给主调函数中的调用表达式。功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数说明:

函数中可有多个return语句,执行到哪个return语句,那个语句起作用

若无return语句,遇到函数结束的“}”时,自动返回调用函数

C语言程序设计

函数与编译预处理例:计算表达式的值

x²-x+1(x<0)x³+x+3(x>0)

Y=floaty(floatx){if(x<0)return(x*x-x+1);elsereturn(x*x*x+x+3);}在定义函数是对函数值说明的类型一般应该与return语句中的表达式类型一致。若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换------函数调用转换,即函数类型决定返回值的类型例如,

intf(){

floatf=7;

f/=2;

returnf;}注意:如果不将函数调用赋值给任何变量,它的返回值将被丢弃。函数返回值为:3,而不是3.5

C语言程序设计

函数与编译预处理如果被调用函数中没有return语句,并不带回一个确定的、用户所希望得到的函数值,但实际上,函数并不是不带回值,只是不带回有用的值,带回的是一个不确定的值。例:printstar(){printf(“****************\n”);}

尽管没有要求printstar函数带回值,但如果程序中出现下面的语句是合法的:

a=printstar();/*输出*****************/

printf(“%d”,a);/*输出16*/

注:a的值不一定有实际意义(printstar函数输出16个字符,返回值是16)

C语言程序设计

函数与编译预处理为了明确表示“不带回值”,可以用“void”定义“无类型”(或称“空类型”)即void型函数:无返回值的函数

例:voidprintstar(){printf(“***********”);}

这样,系统保证不带回任何值,即禁止在调用函数中使用被调函数的返回值。此时,若有:

a=printstar();

编译时会给出错信息。注:一般,凡不要求带回函数值的函数,应定义为void类型例无返回值函数

voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}

C语言程序设计

函数与编译预处理函数的调用

一个c程序有一个主函数和多个函数组成。主函数调用其他函数,其他函数也可相互调用。

C语言的函数调用遵循先定义,后引用的原则。如果对某函数的调用出现在该函数定义之前,必须用说明语句对函数进行声明。

C语言程序设计

函数与编译预处理1.函数的声明

在函数如果要调用某一已经定义了的函数时,一般还应在主调函数中对被调函数进行声明(说明)。作用:告知编译程序本函数将要调用某个函数,并告知相关信息(函数类型、函数名、参数个数、参数类型)函数声明语句的形式:

函数类型名函数名(参数类型说明列表)或

函数类型名函数名();

C语言程序设计

函数与编译预处理例ex2.c函数声明举例

C语言程序设计

函数与编译预处理main()

{floata,b,c;

scanf("%f,%f",&a,&b);c=add(a,b);

printf("sumis%f",c);}floatadd(floatx,floaty){floatz;z=x+y;return(z);}定义add函数对被调用的add函数作声明floatadd(floatx,floaty);/*functiondeclaration*/函数声明与函数定义的区别:

函数定义是用来建立和实现函数的功能,包括指定函数名、函数值类型、形参及其类型、函数体等,是一个完整的、独立的单位。函数声明的作用是把函数的名字、函数类型、形参的类型、个数、顺序通知编译系统,以便在调用该函数时系统按此进行对照检查,它仅仅给出函数的类型、函数名及其参数的类型。

注:函数声明可写为:函数首部:

C语言程序设计

函数与编译预处理

C语言程序设计

函数与编译预处理在函数声明中也可以不写形参名,只写形参的类型,但参数类型、次序和数目必须一致floatadd(float,float);下列情况下,可不作函数声明被调用函数定义出现在主调函数之前,即先定义后调用;floatadd(floatx,floaty){floatz;z=x+y;return(z);}main(){floata,b,c;

scanf("%f,%f",&a,&b);c=add(a,b);

printf("sumis%f",c);}被调函数出现在主调函数之前,不必函数声明Ex3.c已在所有函数定义之前,在函数外部作了声明,则在各个主调函数中不必对所调用的函数再作声明)(例ex1.c)

C语言程序设计

函数与编译预处理charletter(char,char);floatf(float,float);intg(float,float);main(){……}charletter(charch1,charch2){……}floatf(floatx,floaty){……}intg(floatj,floatk){……}已在所有函数定义之前,在函数外部作了声明函数声明位置:程序的数据说明部分(函数内或外);若函数返值是型或void型事实上,int型函数定义之前使用也必须作函数声明,否则系统不知max(a,b)是函数,形参的值无法传给实参,结果出错

C语言程序设计

函数与编译预处理main(){

floata,b;

intc;scanf("%f,%f",&a,&b);c=max(a,b);printf("Maxis%d\n",c);}max(floatx,floaty){floatz;z=x>y?x:y;return(z);}Ex4.cintmax(floatx,floaty);

C语言程序设计

函数与编译预处理2、函数的调用

函数调用的一般形式:有参函数调用形式:

函数名(实参表)无参函数调用形式:函数名()函数调用的方式:函数语句:函数调用可单独成为一个语句例output();

printf(“Hello,World!\n”);

函数表达式:调用函数后的返回值可参加表达式的计算,这时要求被调函数带返回值。例sum=add(a,b);c=fac(n)/(fac(k)*fac(n-k));

函数参数:带返回值的函数调用亦可作为其它函数的参数(实际参数)例printf(“%d”,max(a,b));m=max(a,max(b,c));在主调函数中调用一个函数时,函数名后面括号中的参数(可以是常量、变量、表达式)调用函数的过程是:

为函数的所有形参分配内存单元。计算各个实参表达式的值,一一对应的赋值给相应形参(若是无参函数,上述过程不执行)。

进入函数体,执行函数中的语句,实现函数的功能执行到return语句时,计算return语句中表达式的值(若是无返回值函数,本项不做),返回到主调函数。

释放形参及本函数内的局部变量所占内存,继续执行主调函数中的后继语句。

C语言程序设计

函数与编译预处理

C语言程序设计

函数与编译预处理C语言中,函数调用是值传递方式,即函数的实际参数和形式参数之间的数据传递方向是单向的,只能由实际参数传递给形式参数,而不能由形式参数传递给实际参数,是实际参数向形式参数单向赋值的关系。在内存中,形式参数与实际参数占用不同的内存单元。当调用函数时,给形式参数分配内存单元,将实际参数的值赋值给形式参数,调用后,形式参数单元释放,实际参数仍保留调用前的值,形式参数值的变化不影响实际参数。函数参数及其传递方式形式参数:定义函数时函数名后面括号中的变量名实际参数:调用函数时函数名后面括号中的表达式

C语言程序设计

函数与编译预处理c=max(a,b);(main函数)(max函数)max(intx,inty){intz;z=x>y?x:y;return(z);}例ex4.c比较两个数并输出大者main(){intmax(intx,inty);

inta,b,c;

scanf("%d,%d",&a,&b);c=max(a,b);

printf("Maxis%d",c);}max(intx,inty){intz;z=x>y?x:y;return(z);}形参实参

C语言程序设计

函数与编译预处理

说明:实参必须有确定的值,形参必须指定类型形参与实参类型一致,个数相同,按顺序一一对应

若形参与实参类型不一致,自动按形参类型转换———函数调用转换(按不同类型数据的赋值规则进行转换)

形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放

C语言程序设计

函数与编译预处理例ex5.c计算x的立方#include<stdio.h>floatcube(floatx){return(x*x*x);}main(){floata,product;

printf("Pleaseinputvalueofa:");

scanf("%f",&a);product=cube(a);

printf(”Cubeof%.4fis%.4f\n",a,product);}xaproduct××××28

C语言程序设计

函数与编译预处理参数传递方式

值传递方式方式:函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值特点:

形参与实参占用不同的内存单元单向传递

地址传递方式方式:函数调用时,将数据的存储地址作为参数传递给形参,当然此时的行参只能是能存储地址的变量(指针变量)。

特点:双向传递

C语言程序设计

函数与编译预处理35a:b:调用前:调用结束:35a:b:例ex6.c交换两个数#include<stdio.h>main(){inta=3,b=5;

printf(“a=%d,\tb=%d\n",a,b);

printf("swapped:\n");

swap(a,b);

printf(“a=%d,\tb=%d\n",a,b);}swap(intx,inty){inttemp;temp=x;x=y;y=temp;}调用35x:y:35a:b:swap:temp35a:b:x:35y:

C语言程序设计

函数与编译预处理main(){inti=2,p;p=f(i,++i);

printf("%d",p);}intf(inta,intb){intc;if(a>b)c=1;elseif(a==b)c=0;elsec=-1;return(c);}例ex7.c参数求值顺序main(){inti=2,p;p=f(i,i++);

printf("%d",p);}intf(inta,intb){intc;if(a>b)c=1;elseif(a==b)c=0;elsec=-1;return(c);}运行结果:0运行结果:1实参的求值顺序不确定,因系统而定(TurboC自右向左)

3.函数的嵌套调用

在某函数体中调用了另一个函数,则在该函数被调用的过程中将发生另一次函数调用。这种调用现象称为函数的嵌套调用。

intf1(){…

}

intf2(){…f1();

}

voidmain()

{…

f2();}f2()f1()main()f2()f1()

C语言程序设计

函数与编译预处理例ex8.c编程求组合Cnm=m!/n!(m-n)!longfac(intk)

/*定义求阶乘的函数*/{longf=1;

inti;for(i=1;i<=k;i++)f=f*i;returnf;}longcomb(intm,intn)/*定义组合函数*/{longc;c=fac(m)/(fac(n)*fac(m-n));/*嵌套调用阶乘函数*/returnc;}main(){intn,m;longc;scanf(“%d,%d”,&m,&n);c=comb(m,n);/*调用组合函数*/printf(“%ld”,c);}#include<stdio.h>

longsum(inta,intb);longfactorial(intn);main(){intn1,n2;longa;scanf("%d,%d",&n1,&n2);a=sum(n1,n2);

printf("a=%1d",a);}longsum(inta,intb){longc1,c2;c1=factorial(a);c2=factorial(b);

return(c1+c2);}

longfactorial(intn){longrtn=1;

inti;for(i=1;i<=n;i++)

rtn*=i;

return(rtn);}longsum(inta,intb);longfactorial(intn);文件包含编译预处理命令函数类型说明函数定义函数调用函数调用函数返回值形参实参Ex9.c实现:任意给定的两个数n1,n2,计算:n1!+n2!

C语言程序设计

函数与编译预处理

6.3递归调用定义:函数直接或间接的调用自身叫函数的递归调用f()调f调f2调f1f1()f2()说明C编译系统对递归函数的自调用次数没有限制每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出intf(intx){inty,z;……

z=f(y);…….return(2*z);}intf1(intx){inty,z;……

z=f2(y);…….return(2*z);}intf2(intt){inta,c;……

c=f1(a);…….return(3+c);}

C语言程序设计

函数与编译预处理例ex10.c求n的阶乘#include<stdio.h>int

fac(intn){intf;if(n<0)printf("n<0,dataerror!");elseif(n==0||n==1)f=1;elsef=fac(n-1)*n;return(f);}main(){intn,y;

printf("Inputaintegernumber:");

scanf("%d",&n);

y=fac(n);

printf("%d!=%15d",n,y);}

C语言程序设计

函数与编译预处理

6.4变量的作用域和存储类别内存…….main(){inta;a=10;

printf(“%d”,a);}编译或函数调用时为其分配内存单元1020002001程序中使用变量名对内存操作

C语言程序设计

函数与编译预处理变量的属性数据类型:变量所持有的数据的性质(操作属性)存储属性存储器类型:寄存器、静态存储区、动态存储区作用域:变量在某区域内有效(空间角度)-------局部变量与全局变量生存期:变量值存在的时间(时间角度)-------静态存储方式与动态存储方式变量的存储类型auto-----自动型register-----寄存器型static------静态型extern-----外部型变量定义格式:[存储类型]数据类型变量表;如:intsum;

auto

inta,b,c;

register

inti;

staticfloatx,y;

C语言程序设计

函数与编译预处理内部变量---局部变量定义:在函数内定义,只在本函数内有效说明:main中定义的变量只在main中有效不同函数中同名变量,占不同内存单元形参属于局部变量可定义在复合语句中有效的变量局部变量可用存储类型:autoregisterstatic(默认为auto)floatf1(inta){intb,c;…….}charf2(intx,inty){inti,j;……}main(){intm,n;…….}a,b,c有效x,y,i,j有效m,n有效

C语言程序设计

函数与编译预处理复合语句中变量#defineN5main(){inti;

inta,b;

scanf(“%d,%d”,&a,&b);if(a<b)

{

inttemp; temp=a; a=b; b=temp;

}

printf("%d,%d",a,b);}例不同函数中同名变量main(){inta,b;a=3;b=4;

printf("main:a=%d,b=%d\n",a,b);sub();

printf("main:a=%d,b=%d\n",a,b);}sub(){inta,b;a=6;b=7;

printf("sub:a=%d,b=%d\n",a,b);}运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4

C语言程序设计

函数与编译预处理外部变量(全局变量)定义:在函数外面定义的变量。外部变量的作用域:对于只有一个源程序文件构成的程序,外部变量的作用域是从定义它的位置开始,直至它所在源程序文件的结束。特点:外部变量的使用增加了函数之间传递数据的途径,在外部变量的作用域内的任何函数都能引用该外部变量,一个函数对外部变量的修改,能影响到其它引用这个变量的函数;因此对外部变量的使用不当,会产生意外的错误。

C语言程序设计

函数与编译预处理floatmax,min;floataverage(intn){inti;floatx;

scanf(“%f”,&x);max=min=x;for(i=2;i<n;i++){scanf(“%f”,&x);if(x>max)max=x;elseif(x<min)min=x;sum+=x;}return(sum/n);}main(){intn;floatave;

scanf(“%d”,&n);

ave=average(n);

printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n",max,min,ave);}作用域maxmin

C语言程序设计

函数与编译预处理inta=3,b=5;max(inta,intb){intc;c=a>b?a:b;return(c);}main(){inta=8;

printf(“a=%d\n,b=%d\n,max=%d\n",a,b,max(a,b));}外部变量与局部变量同名时,在内部变量的作用域中,外部变量被屏蔽。例:

运行结果:a=8/*main中的a*/b=5/*全局变量的b*/max=8

C语言程序设计

函数与编译预处理外部变量的作用域是从定义点到本文件结束。如果定义点之前的函数需要引用这些外部变量时,需要在函数内对被引用的外部变量进行说明。外部变量说明的一般形式为:extern数据类型外部变量[,外部变量2……];注意:外部变量的定义和外部变量的说明是两回事。外部变量的定义,必须在所有的函数之外,且只能定义一次。而外部变量的说明,出现在要使用该外部变量的函数内,而且可以出现多次。intp=1,q=5;floatf1(inta){intb,c;…….}intf3(){…..}charc1,c2;charf2(intx,inty){inti,j;……}main(){intm,n;…….}c1,c2的作用范围p,q的作用范围externcharc1,c2;c1,c2的作用范围扩展后c1,c2的作用范围扩展后externcharc1,c2;

C语言程序设计

函数与编译预处理intglobal;/*定义*/externfloatx;

/*说明*/main(){intlocal; . . .}externintglobal;/*说明*/intnumber;/*定义*/func2(){ . . .}floatx;/*定义*/intnumber;/*定义*/func3(){externintglobal;/*说明*/ . . .}file1.cfile2.cfile3.c

对于多文件程序,在一个源文件中定义的外部变量还可以在其它的文件中使用,这时需要在使用它的文件中用extern进行说明,这样的变量称为程序级的变量。

C语言程序设计

函数与编译预处理变量的存储类别------动态存储方式与静态存储方式动态存储方式:程序运行期间根据需要进行动态的分配存储空间的方式。动态存储类别的变量当进入定义它的函数或复合语句时被分配存储空间,当离开时所占内存空间被释放。静态存储方式:程序运行期间分配固定的存储空间的方式。静态存储类别的变量在源程序编译的时候被分配固定的存储空间,从程序开始执行到程序运行结束,一直占用该内存空间,直至程序运行结束,才被释放内存空间。程序区静态存储区动态存储区全局变量、局部静态变量形参变量局部动态变量(autoregister)函数调用现场保护和返回地址等1.静态存储──静态内部变量(1)定义格式:static数据类型内部变量表;(2)存储特点1)静态内部变量属于静态存储。在程序执行过程中,即使所在函数调用结束也不释放。换句话说,在程序执行期间,静态内部变量始终存在,但其它函数是不能引用它们的。2)定义但不初始化,则自动赋以"0"(整型和实型)或'\0'(字符型);且每次调用它们所在的函数时,不再重新赋初值,只是保留上次调用结束时的值!(3)何时使用静态内部变量1)需要保留函数上一次调用结束时的值。2)变量只被引用而不改变其值。内部变量的存储类别

C语言程序设计

函数与编译预处理2.动态存储──自动局部变量(又称自动变量)(1)定义格式:[auto]数据类型变量表;

(2)存储特点1)自动变量属于动态存储方式。在函数中定义的自动变量,只在该函数内有效;函数被调用时分配存储空间,调用结束就释放。在复合语句中定义的自动变量,只在该复合语句中有效;退出复合语句后,也不能再使用,否则将引起错误。2)定义而不初始化,则其值是不确定的。如果初始化,则赋初值操作是在调用时进行的,且每次调用都要重新赋一次初值。3)由于自动变量的作用域和生存期,都局限于定义它的个体内(函数或复合语句),因此不同的个体中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量,也可与该函数内部的复合语句中定义的自动变量同名。建议:系统不会混淆,并不意味着人也不会混淆,所以尽量少用同名自动变量!

C语言程序设计

函数与编译预处理[例]自动变量与静态局部变量的存储特性。

voidauto_static(void){intvar_auto=0;/*自动变量:每次调用都重新初始化*/

staticintvar_static=0; /*静态局部变量:只初始化1次*/

printf(“var_auto=%d,var_static=%d\n”,var_auto,var_static);++var_auto;++var_static;}main(){inti;for(i=0;i<5;i++)auto_static();}

C语言程序设计

函数与编译预处理3.寄存器存储──寄存器变量一般情况下,变量的值都是存储在内存中的。为提高执行效率,C语言允许将局部变量的值存放到寄存器中,这种变量就称为寄存器变量。定义格式如下:

register

数据类型变量表;(1)只有局部变量才能定义成寄存器变量,即全局变量不行。(2)对寄存器变量的实际处理,随系统而异。例如,微机上的MSC和TC将寄存器变量实际当作自动变量处理。(3)允许使用的寄存器数目是有限的,不能定义任意多个寄存器变量。

C语言程序设计

函数与编译预处理外部变量的存储方式外部变量属于静态存储方式:(1)静态外部变量──只允许被本源文件中的函数引用其定义格式为:static数据类型外部变量表;;(2)非静态外部变量──允许被其它源文件中的函数引用定义时缺省static关键字的外部变量,即为非静态外部变量。其它源文件中的函数,引用非静态外部变量时,需要在引用函数所在的源文件中进行说明:extern数据类型外部变量表;注意:在函数内的extern变量说明,表示引用本源文件中的外部变量!而函数外(通常在文件开头)的extern变量说明,表示引用其它文件中的外部变量。

C语言程序设计

函数与编译预处理静态局部变量和静态外部变量同属静态存储方式,但两者区别较大:(1)定义的位置不同。静态局部变量在函数内定义,静态外部变量在函数外定义。(2)作用域不同。静态局部变量属于内部变量,其作用域仅限于定义它的函数内;虽然生存期为整个源程序,但其它函数是不能使用它的。静态外部变量在函数外定义,其作用域为定义它的源文件内;生存期为整个源程序,但其它源文件中的函数也是不能使用它的。(3)初始化处理不同。静态局部变量,仅在第1次调用它所在的函数时被初始化,当再次调用定义它的函数时,不再初始化,而是保留上1次调用结束时的值。而静态外部变量是在函数外定义的,不存在静态内部变量的“重复”初始化问题,其当前值由最近1次给它赋值的操作决定。

C语言程序设计

函数与编译预处理务必牢记:把局部变量改变为静态内部变量后,改变了它的存储方式,即改变了它的生存期。把外部变量改变为静态外部变量后,改变了它的作用域,限制了它的使用范围。因此,关键字“static”在不同的地方所起的作用是不同的。

C语言程序设计

函数与编译预处理

C语言程序设计

函数与编译预处理6.5编译预处理作用:对源程序编译之前做一些处理,生成扩展C

源程序种类宏定义#define文件包含#include条件编译#if--#else--#endif等格式:“#”开头占单独书写行语句尾不加分号

C语言程序设计

函数与编译预处理如if(x==YES)printf(“correct!\n”);elseif(x==NO)printf(“error!\n”);展开后:if(x==1)printf(“correct!\n”);elseif(x==0)printf(“error!\n”);宏定义不带参数宏定义一般形式:#define宏名[宏体]功能:用指定标识符(宏名)表示字符序列(宏体)宏展开:预编译时,用宏体替换宏名---不作语法检查如#defineYES1#defineNO0#definePI3.1415926#defineOUTprintf(“Hello,World”);定义位置:函数外面,通常写在文件开头、函数之前作用域:从定义命令到文件结束#undef可终止宏名作用域格式:

#undef宏名例#defineYES1main(){……..}#undefYES#defineYES0max(){……..}YES原作用域YES新作用域宏定义可嵌套,不能递归例#defineMAXMAX+10()引号中的内容与宏名相同也不置换例#definePI3.14159printf(“2*PI=%f\n”,PI*2);宏展开:

温馨提示

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

评论

0/150

提交评论