下载

2下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 第三章 函数和变量存储

第三章 函数和变量存储.doc

第三章 函数和变量存储

浩哥
2018-09-09 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《第三章 函数和变量存储doc》,可适用于IT/计算机领域

第三章:函数和函数调用第三章:函数和函数调用第三章:函数和函数调用学习目标·使用函数的优点·C语言函数的基本概念·掌握C语言中常用的内置函数·理解函数原型和返回值·熟练掌握自定义函数的定义和调用·熟悉带参数函数的调用·变量的作用域为什么要使用函数大家在前面知道了变量、表达式和程序的概念试想一个程序如果有行我们如果要理解这段代码就必须从头到尾阅读所有的代码而我们这样做的目的有可能只是为了改动其中很少的部分有没有更好的组织代码的方式让我们可以很快的读懂代码呢?再作以下假设如果这段代码要重复十次我们是否要让它重复遍呢?所有的这些问题通过函数就可以迎刃而解了。我们总结一下引入函数主要是这样几个目的:·把程序按语义分成几个部分提高程序的可读性对于比较长的代码我们一般都会把它按功能分为几个部分这样作可以大大提高程序的可读性(这有点类似与我们看一篇文章如果我们能够知道其中一段文字的大意就算不看这段文字细节也不会影响我们理解整篇文章)所以通过函数我们不需要关注程序的所有细节我们就可以理解整个程序的功能如果需要改动其中的某些部分也很快就可以找到改动的地方。·独立的部分可以重复使用如果程序中有多处地方使用了相同的代码那么我们就可以把这部分的代码独立出来这样对这段代码我们就只要写一次了而在多处重复的地方使用就可以了这简化了整个程序同时带来的另一个好处是:如果要改动的话我们也只要改动一个地方就可以了而不需要在程序中改动多处。·通过现成的函数降低程序开发的难度语言功能的强大是因为提供了很多现成的函数供我们直接使用比如输出函数就是一个典型的例子如果你要自己去实现在屏幕上输出文字那将是一个很复杂的过程因为这涉及到了硬件一般人肯定做不了但通过函数我们可以很容易实现(使用printf)。函数的基本概念:·什么是函数函数其实就是一段代码为了能够辨认这段代码我们给这段代码取一个名字叫做函数名。C源程序就是由函数组成的。虽然在前面介绍的程序中都只有一个主函数main()但实际程序往往由多个函数组成。函数是C源程序的基本模块通过对函数模块的调用可以实现特定的功能。用户可把自己的算法编成一个个相对独立的函数模块然后用调用的方法来使用。可以说C程序的全部工作都是由各式各样的函数完成的所以也把C语言称为函数式语言。由于采用了函数模块式的结构C语言易于实现结构化程序设计。使程序的层次结构清晰便于程序的编写、阅读、调试。·函数的分类在C语言中可从不同的角度对函数分类·从函数定义的角度看函数可分为库函数和用户定义函数两种:)库函数由C系统(开发环境)提供用户无须定义也不必在程序中作类型说明只需在程序前包含有该函数原型的头文件即可在程序中直接调用。C语言提供了极为丰富的库函数(多个)比如我们常用到的printf、scanf都叫做库函数。)用户自定义函数由用户按需要写的函数。对于用户自定义函数不仅要在程序中定义函数本身而且在主调函数模块中还必须对该被调函数进行类型说明然后才能使用。在实现系统的时候我们会定义大量的函数。·从函数参数的角度又可把函数分为无参函数和有参函数两种。)无参函数函数定义、函数说明及函数调用中均不带参数。主调函数和被调函数之间不进行参数传送。此类函数通常用来完成一组指定的功能可以返回或不返回函数值。)有参函数也称为带参函数。在函数定义及函数说明时都有参数称为形式参数(简称为形参)。在函数调用时也必须给出参数实际参数(简称为实参)。进行函数调用时主调函数将把实参的值传送给形参供被调函数使用。·C语言提供了极为丰富的库函数这些库函数又可从功能角度作以下分类。)字符类型分类函数用于对字符按ASCII码分类:字母数字控制字符分隔符大小写字母等。)转换函数用于字符或字符串的转换在字符量和各类数字量(整型实型等)之间进行转换在大、小写之间进行转换。)目录路径函数用于文件目录和路径操作。)诊断函数用于内部错误检测。)图形函数用于屏幕管理和各种图形功能。)输入输出函数用于完成输入输出功能。)接口函数用于与DOSBIOS和硬件的接口。)字符串函数用于字符串操作和处理。)内存管理函数用于内存管理。)数学函数用于数学函数计算。)日期和时间函数用于日期时间转换操作。)进程控制函数用于进程管理和控制。)其它函数用于其它各种功能。以上各类函数不仅数量多而且有的还需要硬件知识才会使用因此要想全部掌握则需要一个较长的学习过程。应首先掌握一些最基本、最常用的函数再逐步深入。由于篇幅关系本章只介绍一部分库函数其余部分读者可根据需要查阅有关手册。还应该指出的是在C语言中所有的函数定义包括主函数main在内都是平行的。也就是说在一个函数的函数体内不能再定义另一个函数即不能嵌套定义。但是函数之间允许相互调用也允许嵌套调用。习惯上把调用者称为主调函数。函数还可以自己调用自己称为递归调用。main函数是主函数它可以调用其它函数而不允许被其它函数调用。因此C程序的执行总是从main函数开始完成对其它函数的调用后再返回到main函数最后由main函数结束整个程序。一个C源程序必须有也只能有一个主函数main·函数定义语法和调用函数定义语法:函数返回类型函数名(函数参数函数参数){函数代码}例:函数语法定义。参见图从上面可以看出:函数分为两个部分:函数头和函数体函数头包括:函数返回类型函数名函数参数列表函数体:从’{’开始到’}’结束部分叫做函数体函数要注意三个概念:函数声明、函数定义(实现)和函数调用·函数声明:只包含函数头以分号结束函数声明和变量声明的作用是一样的变量我们必须先声明后使用函数也是一样的使用函数(调用函数)的时候编译器必须要看到函数的声明或者定义。如:intmax(inta,intb)·函数定义(实现):包含函数头和函数体它的作用就是通过代码实现具体函数的功能如:intmax(inta,intb){}·函数调用(使用):在程序中是通过对函数的调用来执行函数体的包括函数名参数应该是具体的值可以使用变量接受该函数的返回值如:intt=max(,)掌握C语言中常用的内置函数C语言的内置函数很多在这里我们将介绍一些常用的函数:见表类别函数名称简介式化输出printf()fprintf(),sprintf(),vprintf(),vfprintf(),vsprintf()格式化输出到屏幕格式化输出到文件格式化输出到字符串格式化输入fscanf(),scanf(),sscanf()分别从文件控制台字符串中读入数据字符相关函数fgetc(),fgets(),fputc(),fputs(),getc(),gets(),putc(),puts(),putchar(),ungetc()从文件或控制台读入字符串把字符串写入文件或控制台isalnum(c),isalpha(c),iscntrl(c),isdigit(c),tolower(c),toupper(c)判断或者转换字符文件操作fopen(),freopen(),fflush(),fclose(),remove(),rename(),tmpfile(),tmpnam(),setvbuf()setbuf()fseek(),ftell(),rewind(),fgetpos(),fsetpos()对文件的操作:包括打开文件、关闭文件、移动文件指针得到设定位置数学函数sin(),cos(),tan(),asin(),acos(),atan(),atan(),sinh(),cosh(),tanh(),exp()log(),log(),pow(),sqrt(),ceil(),floor(),fabs(),ldexp(),frexp(),modf(),fmod()数学函数:包括三角函数平方开方等日期与时间函数clock(),time(),difftime(),mktime(),asctime(),ctime(),strftime()取系统的时间以及对时间进行转换实用函数atof(),atoi(),atol(),strtod(),strtoul(),rand(),srand(),calloc(),malloc(),realloc(),free(),abort(),exit(),atexit(),system(),getenv(),bsearch(),qsort(),abs(),labs(),div(),ldiv()数据类型转换随机数内存操作内存进程相关函数以及排序查找函数诊断assert()诊断函数字符串函数strcpy(),strncpy(),strcat(),strncat(),strcmp(),strncmp(),strchar(),strrchr(),strspn(),strcspn(),strpbrk(),strstr(),strlen(),strerror(),strtok()处理字符串的拷贝、拼接比较等操作以及求字符串的长度错误处理函数clearerr(),feof(),ferror(),perror()各种错误处理目录路径函数chdirchdrivegetdiskfreegetdrivegetdriversmkdirrmdirsearchenv改变得到当前驱动器、改变得到当前目录、得到磁盘的剩余空间、建立删除目录、在指定目录查找文件理解函数返回值函数的值是指函数被调用之后执行函数体中的程序段所取得的并返回给主调函数的值。如调用正弦函数取得正弦值调用前面例子中max函数取得的两个数的最大数。对函数的值(或称函数返回值)有以下一些说明:函数的值只能通过return语句返回主调函数。return语句的一般形式为:return表达式或者为:return(表达式)该语句的功能是计算表达式的值并返回给主调函数。·在函数中允许有多个return语句但每次调用只能有一个return语句被执行因此只能返回一个函数值。·函数值的类型和函数定义中函数的类型应保持一致。如果两者不一致则以函数类型为准自动进行类型转换。·如函数值为整型在函数定义时可以省去类型说明。·不返回函数值的函数可以明确定义为"空类型"类型说明符为"void"。如函数s并不向主函数返函数值可定义为:voids(intn){……}一旦函数被定义为空类型后就不能在主调函数中使用被调函数的函数值了。例如在定义s为空类型后在主函数中写下述语句sum=s(n)就是错误的。为了使程序有良好的可读性并减少出错凡不要求返回值的函数都应定义为空类型。函数说明在主调函数中调用某函数之前应对该被调函数进行说明(函数声明)。在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型以便在主调函数中按此种类型对返回值作相应的处理。对被调函数的说明的一般格式为:类型说明符被调函数名(类型形参类型形参…)或为:类型说明符被调函数名(类型类型…) 括号内给出了形参的类型和形参名或只给出形参类型。这便于编译系统进行检错以防止可能出现的错误。C语言中又规定在以下几种情况时可以省去主调函数中对被调函数的函数说明。·如果被调函数的返回值是整型或字符型时可以不对被调函数作说明而直接调用。这时系统将自动对被调函数返回值按整型处理。·当被调函数的函数定义出现在主调函数之前时在主调函数中也可以不对被调函数再作说明而直接调用。例如函数add的定义放在main函数之前因此可在main函数中省去对add函数的函数说明intadd(inta,intb)。·如在所有函数定义之前在函数外预先说明了各个函数的类型则在以后的各主调函数中可不再对被调函数作说明。函数声明实例:charstr(inta)main(){charc=str()}charstr(inta){……}其中第一对str函数预先作了说明。因此在以后各函数中无须对str和f函数再作说明就可直接调用。·无参函数的定义和调用:定义格式:类型说明符函数名(){类型说明语句}  说明:其中类型说明符和函数名称为函数头。类型说明符指明了本函数的类型函数的类型实际上是函数返回值的类型。函数名是由用户定义的标识符函数名后有一个空括号其中无参数但括号不可少{}中的内容称为函数体。在函数体中也有类型说明这是对函数体内部所用到的变量的类型说明。在很多情况下都不要求无参函数有返回值此时函数类型符可以写为void。我们可以这样定义一个无参函数:例:定义一个无参函数显示一个消息voidShowMsg(){printf("ITJOB!n")} 这里Hello函数是一个无参函数当被其它函数调用时输出ITJOB!字符串。调用格式:voidmain(){ShowMsg()调用ShowMsg函数}·有参函数的定义和调用定义格式:类型说明符函数名(形式参数表){类型说明语句}  有参函数比无参函数多了形式参数表。在形参表中给出的参数称为形式参数它们可以是各种类型的变量各参数之间用逗号间隔。在进行函数调用时主调函数将赋予这些形式参数实际的值。形参既然是变量当然必须给以类型说明。例:定义一个函数用于求两个数中的大数intadd(inta,intb){intretret=abreturnret}第一行说明add函数是一个整型函数其返回的函数值是一个整数。形参为ab。ab的具体值是由主调函数在调用时传送过来的。在{}中的函数体内定义了返回变量returnret它表示把ret的结果返回给add函数的调用者。调用格式:voidmain(){intcc=add(,)}以上是带参函数的调用格式其中和是实参(实际参数)实参可以是常数变量或其它构造类型数据及表达式。各实参之间用逗号分隔调用函数的时候会按顺序把实参传给形参也就是把传给a传给b。形参和实参一定要匹配也就是参数类型、个数要匹配比如intadd(intint)表示实参应该要两个整数值以下的调用都是错误的:add(,)、add(,,)如果函数作为另一个函数调用的实际参数出现(函数实参)。这种情况是把该函数的返回值作为实参进行传送要求该函数必须有返回值。例如:printf("d",add(,))就是把add调用的返回值又作为printf函数的实参来使用的。·函数的参数前面已经介绍过函数的参数分为形参和实参两种。在本小节中进一步介绍形参、实参的特点和两者的关系。形参出现在函数定义中在整个函数体内都可以使用离开该函数则不能使用。实参出现在主调函数中进入被调函数后实参变量也不能使用。形参和实参的功能是作数据传送。发生函数调用时主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。函数的形参和实参具有以下特点:·形参变量只有在被调用时才分配内存单元在调用结束时立刻释放所分配的内存单元。因此形参只在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。·参可以是常量、变量、表达式、函数等无论实参是何种类型的量在进行函数调用时它们都必须具有确定的值以便把这些值传送给形参。因此应预先用赋值输入等办法使实参获得确定值。·实参和形参在数量上类型上顺序上应严格一致否则会发生"类型不匹配"的错误。·函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参而不能把形参的值反向地传送给实参。因此在函数调用过程中形参的值发生改变而实参中的值不会变化。例:把字符转换为大写voidtoUpper(charc){if(c>=c<=)c=cprintf("ch=cn",c)}voidmain(){charcprintf("inputcharn")scanf("c",c)toUpper(c)printf("ch=cn",c)}本程序中定义了一个函数toUpper该函数的功能是把小写字母转换为大写。在主函数中输入c值并作为实参在调用时传送给toUpper函数的形参量c(注意本例的形参变量和实参变量的标识符都为c但这是两个不同的量各自的作用域不同)。在主函数中用printf语句输出一次c值这个c值是实参c的值。在函数toUpper中也用printf语句输出了一次c值这个c值是形参最后取得的c。从运行情况看输入c值为'd'。即实参c的值为'd'。把此值传给函数toUpper时形参c的初值也为'd'在执行函数过程中形参c的值变为'D'。返回主函数之后输出实参n的值仍为'd'。可见实参的值不随形参的变化而变化。变量的作用域在讨论函数的形参变量时曾经提到形参变量只在被调用期间才分配内存单元调用结束立即释放。这一点表明形参变量只有在函数内才是有效的离开该函数就不能再使用了。这种变量有效性的范围称变量的作用域。不仅对于形参变量C语言中所有的变量都有自己的作用域。变量说明的方式不同其作用域也不同。C语言中的变量按作用域范围可分为两种即局部变量和全局变量。·局部变量局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内离开该函数后再使用这种变量是非法的。例:局部变量intf(inta)*函数f*{intb,cabc是函数f的局部变量}voidmain(){inta,xmain局部变量f(a)}在函数f内定义了三个变量a为形参b,c为一般变量。在f的范围内a,b,c有效或者说a,b,c变量的作用域限于f内。a,x的作用域限于main函数内。关于局部变量的作用域还要说明以下几点:·函数中定义的变量也只能在主函数中使用不能在其它函数中使用。同时主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数它与其它函数是平行关系。·形参变量是属于被调函数的局部变量实参变量是属于主调函数的局部变量。·允许在不同的函数中使用相同的变量名它们代表不同的对象分配不同的单元互不干扰也不会发生混淆。比如上面f和main中的变量a·在复合语句中也可定义变量其作用域只在复合语句范围内。复合语句变量见图。本程序在main中定义了i,j,k三个变量其中k未赋初值。而在复合语句内又定义了一个变量k并赋初值为。应该注意这两个k不是同一个变量。在复合语句外由main定义的k起作用而在复合语句内则由在复合语句内定义的k起作用。因此程序第行的k为main所定义其值应为。第行输出k值该行在复合语句内由复合语句内定义的k起作用其初值为故输出值为第行输出ik值。i是在整个程序中有效的第行对i赋值为故以输出也为。而第行已在复合语句之外输出的k应为main所定义的k此k值由第行已获得为故输出也为。·全局变量全局变量也称为外部变量它是在函数外部定义的变量。它不属于哪一个函数它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量一般应作全局变量说明。只有在函数内经过说明的全局变量才能使用。全局变量的说明符为extern。但在一个函数之前定义的全局变量在该函数内使用可不再加以说明。例:想想全局变量x,y作用域和全局变量a,b作用域inta,b*外部变量*voidf()*函数f*{}floatx,y*外部变量*intfz()*函数fz*{}main()*主函数*{}从上例可以看出a、b、x、y都是在函数外部定义的外部变量都是全局变量。但x,y定义在函数f之后而在f内又无对x,y的说明所以它们在f内无效。a,b定义在源程序最前面因此在f,f及main内不加说明也可使用。例输入正方体的长宽高l,w,h。求体积及三个面x*y,x*z,y*z的面积。ints,s,sintvs(inta,intb,intc){intvv=a*b*cs=a*bs=b*cs=a*creturnv}voidmain(){intv,l,w,hprintf("ninputlength,widthandheightn")scanf("ddd",l,w,h)v=vs(l,w,h)printf("v=ds=ds=ds=dn",v,s,s,s)}本程序中定义了三个外部变量s,s,s用来存放三个面积其作用域为整个程序。函数vs用来求正方体体积和三个面积函数的返回值为体积v。由主函数完成长宽高的输入及结果输出。由于C语言规定函数返回值只有一个当需要增加函数的返回数据时用外部变量是一种很好的方式。本例中如不使用外部变量在主函数中就不可能取得v,s,s,s四个值。而采用了外部变量在函数vs中求得的s,s,s值在main中仍然有效。因此外部变量是实现函数之间数据通讯的有效手段。对于全局变量还有以下几点说明:·对于局部变量的定义和说明可以不加区分。而对于外部变量则不然外部变量的定义和外部变量的说明并不是一回事。外部变量定义必须在所有的函数之外且只能定义一次。其一般形式为:extern类型说明符变量名变量名…其中方括号内的extern可以省去不写。例如:inta,b等效于:externinta,b而外部变量说明出现在要使用该外部变量的各个函数内在整个程序内可能出现多次外部变量说明的一般形式为:extern类型说明符变量名变量名…外部变量在定义时就已分配了内存单元外部变量定义可以有初始值外部变量说明不能再赋初始值只是表明在函数内要使用某外部变量。·外部变量可加强函数模块之间的数据联系但是又使函数要依赖这些变量因而使得函数的独立性降低。从模块化程序设计的观点来看这是不利的因此在不必要时尽量不要使用全局变量。·在同一源文件中允许全局变量和局部变量同名。在局部变量的作用域内全局变量不起作用。例intvs(intk,intw){externinthintvv=k*w*hreturnv}main(){externintw,hintk=printf("v=d",vs(k,w))intk=,w=,h=}本例程序中外部变量在最后定义因此在前面函数中对要用的外部变量必须进行说明。外部变量lw和vs函数的形参kw同名。外部变量都赋了初始值main函数中也对k作了初始化赋值。执行程序时在printf语句中调用vs函数实参l的值应为main中定义的l值等于外部变量k在main内不起作用实参w的值为外部变量w的值为进入vs后这两个值传送给形参k和w在vs函数返回的v值是k,v,h的乘积k,w是局部变量(分别为和)h是外部变量值(等于)所以最后的结果就是。·变量的存储类型各种变量的作用域不同就其本质来说是因变量的存储类型不同。所谓存储类型是指变量占用内存空间的方式也称为存储方式。变量的存储方式可分为"静态存储"和"动态存储"两种。静态存储变量通常是在变量定义时就分定存储单元并一直保持不变直至整个程序结束。动态存储变量是在程序执行过程中使用它时才分配存储单元使用完毕立即释放。典型的例子是函数的形式参数在函数定义时并不给形参分配存储单元只是在函数被调用时才予以分配调用函数完毕立即释放。如果一个函数被多次调用则反复地分配、释放形参变量的存储单元。从以上分析可知静态存储变量是一直存在的而动态存储变量则时而存在时而消失。我们又把这种由于变量存储方式不同而产生的特性称变量的生存期。生存期表示了变量存在的时间。生存期和作用域是从时间和空间这两个不同的角度来描述变量的特性这两者既有联系又有区别。一个变量究竟属于哪一种存储方式并不能仅从其作用域来判断还应有明确的存储类型说明。在C语言中对变量的存储类型说明有以下四种:auto    自动变量register  寄存器变量extern   外部变量static   静态变量自动变量和寄存器变量属于动态存储方式外部变量和静态变量属于静态存储方式。在介绍了变量的存储类型之后可以知道对一个变量的说明不仅应说明其数据类型还应说明其存储类型。因此变量说明的完整形式应为:存储类型说明符数据类型说明符变量名变量名…例如:staticinta,b         说明a,b为静态类型变量autocharc,c        说明c,c为自动字符变量staticinta={,,,,}  说明a为静整型数组externintx,y         说明x,y为外部整型变量下面分别介绍以上四种存储类型:·自动变量的类型说明符为auto。这种存储类型是C语言程序中使用最广泛的一种类型。C语言规定函数内凡未加存储类型说明的变量均视为自动变量也就是说自动变量可省去说明符auto。在前面各章的程序中所定义的变量凡未加存储类型说明符的都是自动变量。例如:{inti,j,kcharc}等价于:{autointi,j,kautocharc}自动变量具有以下特点:)自动变量的作用域仅限于定义该变量的个体内。在函数中定义的自动变量只在该函数内有效。在复合语句中定义的自动变量只在该复合语句中有效。例如:intkv(inta){autointx,y{autocharc}*c的作用域*……}*a,x,y的作用域*)自动变量属于动态存储方式只有在使用它即定义该变量的函数被调用时才给它分配存储单元开始它的生存期。函数调用结束释放存储单元结束生存期。因此函数调用结束之后自动变量的值不能保留。在复合语句中定义的自动变量在退出复合语句后也不能再使用否则将引起错误。例如:自动存储变量实例voidmain(){autointaprintf("ninputanumber:n")scanf("d",a)if(a>){autoints,ps=aap=a*a}printf("s=dp=dn",s,p)}s,p是在复合语句内定义的自动变量只能在该复合语句内有效。而程序的第行却是退出复合语句之后用printf语句输出s,p的值这显然会引起错误。)由于自动变量的作用域和生存期都局限于定义它的个体内(函数或复合语句内)因此不同的个体中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量也可与该函数内部的复合语句中定义的自动变量同名。例自动变量同名的示例voidmain(){autointa,s=,p=printf("ninputanumber:n")scanf("d",a)if(a>){autoints,ps=aap=a*aprintf("s=dp=dn",s,p)}printf("s=dp=dn",s,p)}本程序在main函数中和复合语句内两次定义了变量s,p为自动变量。按照C语言的规定在复合语句内应由复合语句中定义的s,p起作用故s的值应为aap的值为a*a。退出复合语句后的s,p应为main所定义的s,p其值在初始化时给定均为。从输出结果可以分析出两个s和两个p虽变量名相同但却是两个不同的变量。)对构造类型的自动变量如数组等不可作初始化赋值。·外部变量的类型说明符为extern。在前面介绍全局变量时已介绍过外部变量。这里再补充说明外部变量的几个特点:·外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变是是从它的作用域提出的外部变量从它的存储方式提出的表示了它的生存期。当一个源程序由若干个源文件组成时在一个源文件中定义的外部变量在其它的源文件中也有效。例如:有一个源程序由源文件FC和FC组成FCinta,b*外部变量定义*charc*外部变量定义*main(){……}FCexterninta,b*外部变量说明*externcharc*外部变量说明*func(intx,y){……}在FC和FC两个文件中都要使用a,b,c三个变量。在FC文件中把a,b,c都定义为外部变量。在FC文件中用extern把三个变量说明为外部变量表示这些变量已在其它文件中定义并把这些变量的类型和变量名编译系统不再为它们分配内存空间。对构造类型的外部变量如数组等可以在说明时作初始化赋值若不赋初值则系统自动定义它们的初值为。·静态变量静态变量的类型说明符是static。静态变量当然是属于静态存储方式但是属于静态存储方式的量不一定就是静态变量,例如外部变量虽属于静态存储方式但不一定是静态变量必须由static加以定义后才能成为静态外部变量或称静态全局变量。对于自动变量前面已经介绍它属于动态存储方式。但是也可以用static定义它为静态自动变量或称静态局部变量从而成为静态存储方式。由此看来一个变量可由static进行再说明并改变其原有的存储方式。·静态局部变量在局部变量的说明前再加上static说明符就构成静态局部变量。例如:staticinta,bstaticfloatarray={,,,,}静态局部变量属于静态存储方式它具有以下特点:<>静态局部变量在函数内定义但不象自动变量那样当调用时就存在退出函数时就消失。静态局部变量始终存在着也就是说它的生存期为整个源程序。<>静态局部变量的生存期虽然为整个源程序但是其作用域仍与自动变量相同即只能在定义该变量的函数内使用该变量。退出该函数后尽管该变量还继续存在但不能使用它。<>允许对构造类静态局部量赋初值。在数组一章中介绍数组初始化时已作过说明。若未赋以初值则由系统自动赋以值。<>对基本类型的静态局部变量若在说明时未赋以初值则系统自动赋予值。而对自动变量不赋初值则其值是不定的。根据静态局部变量的特点可以看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用但如再次调用定义它的函数时它又可继续使用而且保存了前次被调用后留下的值。因此当多次调用一个函数且要求在调用之间保留某些变量的值时可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的但全局变量有时会造成意外的副作用因此仍以采用局部静态变量为宜。·静态全局变量全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。全局变量本身就是静态存储方式静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别在于非静态全局变量的作用域是整个源程序当一个源程序由多个源文件组成时非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域即只在定义该变量的源文件内有效在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内只能为该源文件内的函数公用因此可以避免在其它源文件中引起错误。从以上分析可以看出把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域限制了它的使用范围。因此static这个说明符在不同的地方所起的作用是不同的。应予以注意。·寄存器变量上述各类变量都存放在存储器内因此当对一个变量频繁读写时必须要反复访问内存储器从而花费大量的存取时间。为此C语言提供了另一种变量即寄存器变量。这种变量存放在CPU的寄存器中使用时不需要访问内存而直接从寄存器中读写这样可提高效率。寄存器变量的说明符是register。对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量。例:求到的和main(){registeri,s=for(i=i<=i)s=siprintf("s=dn",s)}本程序循环次i和s都将频繁使用因此可定义为寄存器变量。对寄存器变量还要说明以下几点:)只有局部自动变量和形式参数才可以定义为寄存器变量。因为寄存器变量属于动态存储方式。凡需要采用静态存储方式的量不能定义为寄存器变量。)在TurboCMSC等微机上使用的C语言中实际上是把寄存器变量当成自动变量处理的。因此速度并不能提高。而在程序中允许使用寄存器变量只是为了与标准C保持一致。)即使能真正使用寄存器变量的机器由于CPU中寄存器的个数是有限的因此使用寄存器变量的个数也是有限的。·函数的默认参数·内联函数·内部函数和外部函数函数一旦定义后就可被其它函数调用。但当一个源程序由多个源文件组成时,在一个源文件中定义的函数能否被其它源文件中的函数调用呢为此C语言又把函数分为两类:·内部函数如果在一个源文件中定义的函数只能被本文件中的函数调用而不能被同一源程序其它文件中的函数调用这种函数称为内部函数。定义内部函数的一般形式是:static类型说明符函数名(形参表)例如:staticintf(inta,intb)内部函数也称为静态函数。但此处静态static的含义已不是指存储方式而是指对函数的调用范围只局限于本文件。因此在不同的源文件中定义同名的静态函数不会引起混淆。·外部函数外部函数在整个源程序中都有效其定义的一般形式为:extern类型说明符函数名(形参表)例如:externintf(inta,intb)如在函数定义中没有说明extern或static则隐含为extern。在一个源文件的函数中调用其它源文件中定义的外部函数时应用extern说明被调函数为外部函数。例如:外部函数定义FC(源文件一)main(){externintf(inti)*外部函数说明表示f函数在其它源文件中*}FC(源文件二)externintf(inti)*外部函数定义*{}内容总结根据不同的分类标准可以将函数进行分类:·库函数:由C系统提供的函数·用户定义函数:由用户自己定义的函数·有返回值的函数向调用者返回函数值应说明函数类型(即返回值的类型)·无返回值的函数:不返回函数值说明为空(void)类型·有参函数:主调函数向被调函数传送数据·无参函数:主调函数与被调函数间无数据传送·内部函数:只能在本源文件中使用的函数·外部函数:可在整个源程序中使用的函数。函数定义的一般形式类型说明符函数名(形参表)方括号内为可选项。函数调用的一般形式函数名(实参表)。函数的参数分为形参和实参两种形参出现在函数定义中实参出现在函数调用中发生函数调用时将把实参的值传送给形参。函数的值是指函数的返回值它是在函数中由return语句返回的。变量的作用域是指变量在程序中的有效范围分为局部变量和全局变量。变量的生存期,自动变量auto、register变量extern变量static变量。内部函数:在一个源文件中定义的函数只能被本文件中的函数调用而不能被同一源程序其它文件中的函数调用这种函数称为内部函数。定义内部函数的一般形式是:static类型说明符函数名(形参表)和外部函数:在整个源程序中都有效其定义的一般形式为:extern类型说明符函数名(形参表)独立实践·实践题目:写一个函数判断两个数之间有多少个素数并输出所有素数·实践题目:利用递归函数调用方式将所输入的个字符以相反顺序打印出来·实践题目:使用静态局部变量计算一个整数的阶乘(不要使用递归)理解静态局部变量的记忆功能。·实践题目:编写四个Swap()函数(voidSwap(inta,intb),voidSwap(int*,int*),voidSwap(inta,intb),intswap(int*,int*))看看他们能否实现两个数的交换如果不能请说明理由。·实践题目:编写一个函数以数组为形式参数实现所有数组元素的求和并输出在函数定义的时候在函数体中使用sizeof运算符计算该形参数组的大小。理解数组作为形参的特殊性。

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

评分:

/29

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利