《简单程序设计..ppt》由会员分享,可在线阅读,更多相关《简单程序设计..ppt(31页珍藏版)》请在课桌文档上搜索。
1、第6章 简单程序设计,6.1 程序开发过程6.2 文件之间的信息共享6.3 头文件6.4 生存期 Return,6.1 程序开发过程,C+程序一般是多文件结构的。这样,每个文件的长度相对较小,功能相对单一,维护方便。便于多人合作开发。若一个文件的代码有改变只需重新编译此文件而不必重新编译所有文件。预编译负责处理各个源文件和头文件中的预编译指令;编译程序将源程序翻译成对应的二进制代码文件,扩展名为.obj;连接程序将所有.obj和用到的库文件连接起来,形成一个可执行文件。Return,6.2 文件之间的信息共享,6.2.1外部变量6.2.2外部函数6.2.3静态全局变量与静态函数Return,6
2、.2.1外部变量,在函数外部定义的变量称为外部变量。外部变量不属于任何一个函数,其作用域是:从外部变量的定义位置开始,到本文件结束为止。外部变量可被作用域内的所有函数直接引用,所以外部变量又称全局变量。(1)外部变量可加强函数模块之间的数据联系,但又使这些函数依赖这些外部变量,因而使得这些函数的独立性降低。(2)在同一源文件中,允许外部变量和内部变量同名。在内部变量的作用域内,外部变量将被屏蔽而不起作用。(3)定义点前的函数引用这些外部变量时,需要在函数内对被引用的外部变量进行说明。外部变量说明的一般形式为:extern 数据类型 外部变量,外部变量2;注意:外部变量的定义和说明是两回事。外部
3、变量的定义,必须在所有的函数之外,且只能定义一次。而外部变量的说明,出现在要使用该外部变量的函数内,而且可出现多次。return,6.2.2外部函数,函数无全局与局部之分,一般是可以共享的。在另一文件中要使用这个函数,只要说明一下函数原型即可。也就是C+中函数的说明默认是extern的。所以可在原型说明时省略前面的extern。return,6.2.3静态全局变量与静态函数,若不希望某文件中定义的某些变量或函数被其它文件使用,可将这些变量或函数定义成静态(static)的。使用static全局变量和函数的好处:可将某些实现细节封装进来,既安全又简化了文件之间的接口;不同文件可使用同名变量或函数
4、而不必担心名字冲突。return,不同的存储类型,在语言中,对变量的存储类型说明有以下四种:自动变量(auto)、寄存器变量(register)、外部变量(extern)、静态变量(static)。自动变量和寄存器变量属于动态存储方式,外部变量和静态内部变量属于静态存储方式。,内部变量的存储方式,1静态存储静态内部变量(1)定义格式:static 数据类型 内部变量表;(2)存储特点:静态内部变量属于静态存储。在程序执行过程中,即使所在函数调用结束也不释放。换句话说,在程序执行期间,静态内部变量始终存在,但其它函数是不能引用它们的。定义若不初始化,则自动赋以(整型和实型)或0(字符型);且每次
5、调用它们所在的函数时,不再重新赋初值,只是保留上次调用结束时的值!(3)何时使用静态内部变量:需要保留函数上一次调用结束时的值。变量只被引用而不改变其值。,静态存储例:,#include#define RESET trueunsigned counter(bool reset=!RESET)static unsigned cnt=0;if(reset)return cnt=0;return+cnt;void main()cout counter();cout counter();cout counter();cout counter(RESET);cout counter();cout cou
6、nter();coutn;,2动态存储自动局部变量(又称自动变量)(1)定义格式:auto 数据类型 变量表;(2)存储特点1)自动变量属于动态存储方式。在函数中定义的自动变量,只在该函数内有效;函数被调用时分配存储空间,调用结束就释放。在复合语句中定义的自动变量,只在该复合语句中有效;退出复合语句后,也不能再使用,否则将引起错误。2)定义而不初始化,则其值是不确定的。如果初始化,则赋初值操作是在调用时进行的,且每次调用都要重新赋一次初值。3)由于自动变量的作用域和生存期,都局限于定义它的个体内(函数或复合语句),因此不同的个体中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量,也可与
7、该函数内部的复合语句中定义的自动变量同名。建议:系统不会混淆,并不意味着人也不会混淆,所以尽量少用同名自动变量!,3寄存器存储寄存器变量一般情况下,变量的值都是存储在内存中的。为提高执行效率,语言允许将局部变量的值存放到寄存器中,这种变量就称为寄存器变量。定义格式如下:register 数据类型 变量表;(1)只有局部变量才能定义成寄存器变量,即全局变量不行。(2)对寄存器变量的实际处理,随系统而异。例如,微机上的MSC和TC 将寄存器变量实际当作自动变量处理。(3)允许使用的寄存器数目是有限的,不能定义任意多个寄存器变量。Return,外部变量的存储方式,外部变量属于静态存储方式:(1)静态
8、外部变量只允许被本源文件中的函数引用其定义格式为:static 数据类型 外部变量表;(2)非静态外部变量允许被其它源文件中的函数引用定义时缺省static关键字的外部变量,即为非静态外部变量。其它源文件中的函数,引用非静态外部变量时,需要在引用函数所在的源文件中进行说明:extern 数据类型 外部变量表;注意:在函数内的extern变量说明,表示引用本源文件中的外部变量!而函数外(通常在文件开头)的extern变量说明,表示引用其它文件中的外部变量。,静态局部变量和静态外部变量同属静态存储方式,但两者区别较大:(1)定义的位置不同。静态局部变量在函数内定义,静态外部变量在函数外定义。(2)
9、作用域不同。静态局部变量属于内部变量,其作用域仅限于定义它的函数内;虽然生存期为整个源程序,但其它函数是不能使用它的。静态外部变量在函数外定义,其作用域为定义它的源文件内;生存期为整个源程序,但其它源文件中的函数也是不能使用它的。(3)初始化处理不同。静态局部变量,仅在第1次调用它所在的函数时被初始化,当再次调用定义它的函数时,不再初始化,而是保留上一次调用结束时的值。而静态外部变量是在函数外定义的,不存在静态内部变量的“重复”初始化问题,其当前值由最近一次给它赋值的操作决定。,务必牢记:把局部变量改变为静态内部变量后,改变了它的存储方式,即改变了它的生存期。把外部变量改变为静态外部变量后,改
10、变了它的作用域,限制了它的使用范围。因此,关键字“static”在不同的地方所起的作用是不同的。Return,6.3 头文件,一个大程序,通常分为多个模块,并由多个程序员分别编程。有了文件包含处理功能,就可以将多个模块共用的数据(如符号常量和数据结构)或函数,集中到一个单独的文件中。这样,凡是要使用其中数据或调用其中函数的程序员,只要使用文件包含处理功能,将所需文件包含进来即可,不必再重复定义它们,从而减少重复劳动。6.3.1#include指令6.3.2 头文件内容6.3.3 预编译指令 Return,6.3.1#include指令,#include指令告诉预编译程序,将其后的文件内容插入到
11、当前文件中。一般形式为:#include 或#include”文件名”两者不同在于预编译程序查找文件的路径不同。前者仅在C+系统目录的include子目录中找;后者先在用户程序的当前目录下找,若找不到再到系统目录下找。#include指令可以嵌套。所包含文件只要是文本文件均可。所以除.h外,.txt亦可。return,6.3.2 头文件内容,一般放入以下内容:预编译指令:#infine、#ifdef、#endif、#include函数声明内联函数定义类型定义外部数据声明常量定义注释 总之,多个文件可能要使用的一般放到头文件中;而放入后若多个文件用到此头文件会引进冲突的内容则不应放入头文件中。r
12、eturn,6.3.3 预编译指令,1.条件编译指令:#if、#elif、#endif、#ifdef、#ifndef等。用法与if类似,预编译器可以根据条件确定保留或不保留程序文件中的某些内容。2.#define指令,#ifdef#endif和#ifndef#endif,1一般格式 ifdef 标识符 程序段1;else 程序段2;endif2功能:当“标识符”已经被#define命令定义过,则编译程序段1,否则编译程序段2。利用条件编译,还可使同一源程序即适合于调试(进行程序跟踪、打印较多的状态或错误信息),又适合高效执行要求。3关于#ifndef#endif命令格式与#ifdef#endi
13、f命令一样,功能正好与之相反。,#if#endif,1一般格式 if 常量表达式 程序段1;else 程序段2;endif2功能:当表达式为非0(“逻辑真”)时,编译程序段1,否则编译程序段2。return,常用的头文件,iomanip.h 含有setw等操纵符,其它功能与iostream.h相同math.h 数学函数string.h 字符处理函数ctype.h 字符判断及转换函数stdlib.h 随机函数、数据类型转换、系统控制(如exit(1)stdio.h C+的printf和scanf用到,6.4 生存期,6.4.1生存期与内存6.4.2初始化问题6.4.3局部静态变量Return,6
14、.4.1生存期与内存,内存空间可以分为代码区、全局数据区、堆区和栈区。不同生存期的变量存放的内存区域是不同的。,6.4.2初始化问题,具有静态生存期的变量会由系统自动初始化为0,而系统不对具有局部生存期和动态生存期的变量进行初始化。,6.4.3局部静态变量,函数的局部变量一般具有局部生存期,函数执行结束后其局部状态信息将会丢失。当需要让函数让它记住上次运行的状态,以便进行一些处理时,可将此局部变量设为静态。静态局部变量的如下特性:1.具有静态生存期。即生存期与程序的运行期相同,变量处于内存的全局数据区,而不在栈区,并且系统自动将其初始化为0;2.只被初始化一次;3.在函数退出后,静态局部变量不
15、被释放,保留其值。下次进入函数后静态局部变量还能保留它的值。,宏定义与符号常量,在语言中,“宏”分为无参数的宏(简称无参宏)和有参数的宏(简称有参宏)两种。,无参宏定义符号常量有参宏定义,Return,无参宏定义,1无参宏定义的一般格式#define 标识符 语言符号字符串其中:“define”为宏定义命令;“标识符”为所定义的宏名,通常用大写字母表示,以便于与变量区别;“语言符号字符串”可以是常数、表达式、格式串等。2使用宏定义的优点(1)可提高源程序的可维护性(2)可提高源程序的可移植性(3)减少源程序中重复书写字符串的工作量,3说明(1)宏名一般用大写字母表示,以示与变量区别。但这并非是
16、规定。(2)宏定义不是语句,所以不能在行尾加分号。否则,宏展开时,会将分号作为字符串的1个字符,用于替换宏名。(3)在宏展开时,预处理程序仅以按宏定义简单替换宏名,而不作任何检查。如果有错误,只能由编译程序在编译宏展开后的源程序时发现。(4)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后,到本文件结束。通常,宏定义命令放在文件开头处。(5)在进行宏定义时,可以引用已定义的宏名。(6)对双引号括起来的字符串内的字符,即使与宏名同名,也不进行宏展开。,Return,符号常量,在定义无参宏时,如果“语言符号字符串”是一个常量,则相应的“宏名”就是一个符号常量。恰当命名的符
17、号常量,除具有宏定义的上述优点外,还能表达出它所代表常量的实际含义,从而增强程序的可读性。#define EOF-1/*文件尾*/#define NULL 0/*空指针*/#define MIN 1/*极小值*/#define MAX 31/*极大值*/#define STEP 2/*步长*/,Return,有参宏定义,1带参宏定义的一般格式#define 宏名(形参表)语言符号字符串2带参宏的调用和宏展开(1)调用格式:宏名(实参表)(2)宏展开:用宏调用提供的实参字符串,直接置换宏定义命令行中、相应形参字符串,非形参字符保持不变。3说明(1)定义有参宏时,宏名与左圆括号之间不能留有空格。否
18、则,编译系统将空格以后的所有字符均作为替代字符串,而将该宏视为无参宏。(2)有参宏的展开,只是将实参作为字符串,简单地置换形参字符串,而不做任何语法检查。在定义有参宏时,在所有形参外和整个字符串外,均加一对圆括号。,(3)虽然有参宏与有参函数确实有相似之处,但不同之处更多,主要有以下几个方面:1)调用有参函数时,是先求出实参的值,然后再复制一份给形参。而展开有参宏时,只是将实参简单地置换形参。2)在有参函数中,形参是有类型的,所以要求实参的类型与其一致;而在有参宏中,形参是没有类型信息的,因此用于置换的实参,什么类型都可以。有时,可利用有参宏的这一特性,实现通用函数功能。3)使用有参函数,无论调用多少次,都不会使目标程序变长,但每次调用都要占用系统时间进行调用现场保护和现场恢复;而使用有参宏,由于宏展开是在编译时进行的,所以不占运行时间,但是每引用1次,都会使目标程序增大1次。,Return,