




已阅读5页,还剩43页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第四章 模块化程序设计 (函数),五、变量的存储属性,模块化设计要求研究不同模块(函数、源文件)间变量的关系。 变量两大属性: 数据类型 存储属性,1、数据类型(复习) 通过变量说明(定义)来规定其数据类型: 格式 数据类型关键字 变量名 如 char a; int b,c ; float x,y; 为什么使用变量前要先对其数据类型进行“说明”好比看电影前先买票订座 预留存储空间(如char型为1个字节,int型为2个字节) 确定存储方式(如char型存放ASCII值,int型存放补码值),复习,数据存储形式 字符型按ASCII码存储,其余以补码存储,一个变量的数据类型定义后,就规定了该变量只能存储相应类型的数据。如定义int x,则x只能存放整型数,如果x=3.14159,会被自动转为整型存放。,变量两大属性: 数据类型 存储属性 以下这些都称为变量的存储属性,变量的可用域:一个变量在程序的哪个范围内是可以使用的; 变量的生存期:它什么时候生成以及什么时候被撤消; 变量的存储类型:它存储在哪种类型的存储器中以及用什么机制进行存储。,(一)、局部变量与全局变量 P127,1、局部变量函数内部或复合语句内定义的变量,变量的可用域是指一个变量的标识符在程序的哪个域内才是可以被识别的,也称为可见(或可用)的。大体上可以分为两种:全局可用全局变量与局部可用局部变量。,所有形参都是局部变量; 局部变量只在本函数或本复合语句内才能使用,在此之外不能使用(视为不存在)main函数也不例外。,2、全局变量在函数之外定义的变量,有效作用范围:从定义变量位置开始直到本源文件结束 如果需要将全局变量的作用范围扩展至整个源文件 法1 全部在源文件开头处定义 法2 在引用函数内,用extern说明 法3 在源文件开头处,用extern说明,【例】求程序运行结果 extern int x,y; main( ) clrscr(); printf(“x=%d,y=%dn“,x,y); int x=100,y=200;,结果:x=100,y=200,去掉第一行试试,如果要将全局变量作用范围扩展到其他源文件,只需在使用这些变量的文件中对变量用extern加以说明。,int a=3,b=5; max(int a,int b) int c; c=ab?a:b; return c; main() int a=8; printf(“%dn“,max(a,b); ,【例】求程序运行结果,如果主函数中没有int a=8,结果?,【结果】 5,如果让主函数中int a=4或a=-1,结果?,【结果】 均为 5,【结果】 8,void num() extern int x,y; int a=15,b=10; x=a-b; y=a+b; int x,y; main() int a=7,b=5; x=a+b; y=a-b; num(); printf(“%d,%dn“,x,y); ,【例】求程序运行结果,如果第二行不加上extern呢?,【结果】 5,25,【结果】 12,2,int a; fun(int i) a+=2*i; return a; main() int a=10; clrscr( ); printf(“%d,%dn“,fun(a),a); ,【例】求程序运行结果,【结果】 20,10,(二) 动态变量与静态变量,程序,内存中都被分成代码区和数据区两大部分。 而数据区又被分为静态存储区、自动存储区和动态分配区等三部分。 分配在静态存储区的变量在程序开始执行时被创建并自动初始化(数值变量被初始化为0),当程序结束时才被撤销。所以常称静态变量的生存期是永久的。 全局变量就是被分配在静态存储区的。,main() int a=2,i; clrscr( ); for (i=0;i3;i+) printf(“%4d“,f(a); f(int a) int b=0; static int c=3; b+;c+; return a+b+c; ,【例】求程序运行结果,变量跟踪 main( ) f函数 a i b c f(a) 2 0 01 4 7 1 01 5 8 2 01 6 9 【结果】 7 8 9,如果去掉static呢?,【结果】 7 7 7,main() int k=4,m=1,p; clrscr(); p=func(k,m); printf(“%d,“,p); p=func(k,m); printf(“%d“,p); func(int a,int b) static int m=0,i=2; i+=m+1; m=i+a+b; return m; ,【例】求程序运行结果,变量跟踪 main( ) func函数 k m a b m i 4 1 4 1 08 23 4 1 4 1 817 312 【结果】 8, 17,如果去掉static呢?,【结果】 8, 8,#include main() int a=3, b=2, c=1; int b=5, c=12; c-=b*2; printf(“a=%d,b=%d,c=%dn“, a, b, c); a+=c; printf(“a=%d,b=%d,c=%dn“, a, b, c); ,【例】求程序运行结果,【结果】 a=3,b=5,c=2 a=5,b=2,c=1,(三) C语言中变量的存储类型 P132,规定了变量在计算机内部的存放位置决定变量的“寿命”(何时“生”,何时“灭”) 一个完整的变量说明格式如下: 存储类别 数据类型 变量名 如 static int x , y ; C程序的存储类别有: register型(寄存器型)局部自动类型 auto型(自动变量型)局部自动类型 static型(静态变量型)静态局部类型或静态全局类型 extern型(外部变量型)全局类型,C程序的变量存储位置,变量的生存期 静态存储区中的变量:与程序“共存亡” 动态存储区中的变量:与函数“共存亡” 寄存器中的变量:同动态存储区,C程序的变量存储类别,变量的生存期 静态存储区中的变量 与程序“共存亡” 动态存储区中的变量 与函数“共存亡” 寄存器中的变量 同动态存储区, register型(寄存器型) 变量值存放在运算器的寄存器中存取速度快,一般只允许23个,且限于char型和int型,通常用于循环变量(在微机的Turbo C中实际上自动转为auto型)。 auto型(自动变量型) auto 数据类型变量名=初值表达式,; 变量值存放在主存储器的动态存储区(堆栈方式); 优点同一内存区可被不同变量反复使用。 以上两种变量均属于“动态存储型”,即调用函数时才为这些变量分配单元,函数调用结束其值自动消失。,C程序的变量存储类别,变量的生存期 静态存储区中的变量 与程序“共存亡” 动态存储区中的变量 与函数“共存亡” 寄存器中的变量 同动态存储区, static型(静态变量型) 变量值存放在主存储器的静态存储区 程序执行开始至结束,始终占用该存储空间 extern型(外部变量型) 同上,其值可供其他源文件使用 以上两种均属于“静态存储”性质,即从变量定义处开始,在整个程序执行期间其值都存在(都可用!),未说明存储类别时, 函数内定义的变量默认为auto型 函数外定义的变量默认为extern型。,用const声明将变量存储在只读区,C语言除了可以为程序开辟栈区、堆区、静态区外,还可以开辟一个只读区。既然只读区是内存的一个区,所以数据是以变量的形式存储的,但它又是只读的,即不可修改的。所以这也就是把变量定义为只读变量。定义只读变量的方法是在声明变量时使用修饰符const。格式为:,const 数据类型 变量1=初始表达式1,变量2=初始表达式2,,举 例 说 明,通过下面例子说明这3种类型的变量的变化情况:,main( ) auto int a=2; register int b=2; static int c=2; printf(“-a=%d,b=%d,c=%d -n“,a,b,c); f(a); /*调用f*/ f(b); /*调用f*/ f(c); /*调用f*/ printf(“-a=%d,b=%d,c=%d -n“,a,b,c); ,main的局部变量,2,2,2,动态存储区,静态存储区,第一次调用f函数,实参为a=2,int f(int x) auto int a=10; register int b=20; static int c; a=a+x; b=b-x; c=c+x*x; printf(“a=%d,b=%d,c=%dn“,a,b,c); ,main的局部变量,2,2,2,10,0,20,12,18,4,第二次调用f函数,实参为b=2,int f(int x) auto int a=10; register int b=20; static int c; a=a+x; b=b-x; c=c+x*x; printf(“a=%d,b=%d,c=%dn“,a,b,c); ,main的局部变量,2,2,2,10,4,20,12,18,8,第三次调用f函数,实参为c=2,int f(int x) auto int a=10; register int b=20; static int c; a=a+x; b=b-x; c=c+x*x; printf(“a=%d,b=%d,c=%dn“,a,b,c); ,main的局部变量,2,2,2,10,8,20,12,18,12,C语言程序的加工过程,六、模块的编译和链接,1 分别编译 C语言是一种支持模块化程序设计的语言,它允许将一个大型程序分成多个程序文件分别进行编译。这样的好处在于 当程序的一个局部有错误或对局部进行了修改时,可以只重新编译该局部,不需要将整个程序都重新编译。 某些经过考验的函数的目标代码可以添加为的库函数,供其他程序中使用。,2 用项目管理多文件程序的编译与链接过程,多文件程序的编译、链接过程是比较麻烦的。为了方便用户进行多文件程序的编译、链接,各种程序开发软件都提供了用项目(project)管理多文件程序的编译和链接过程。其使用方法因开发工具而异,请参考有关手册。,3 头文件,用户显式地保证程序一致性的基本方法是保持声明的一致性。保持声明一致性的简单办法是提供一个头文件,让头文件中的信息作为各模块之间的接口信息,有利于提供可重用的模块。使用头文件将把程序分为程序头和程序体两部分。 好的头文件应包含如下一些内容: 类型定义,如定义一个枚举类型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 ,3 头文件,宏定义,如#define case break; case 注释 好的头文件不能包含以下内容: 一般函数定义 数据定义,如int a; 常量聚集定义,如 const tbl=/* */; 用户头文件是由用户自己定义的头文件。系统将用双引号方式进行搜索。程序员可以用它们建立各文件之间的信息窗口。 应当注意,修改了头文件时,所有涉及该头文件的程序都应重新编译,所以在编制头文件时应尽量考虑周全;另外,当使用很多头文件时,常常有重复嵌入的情形发生,在这种情形下,应防止标识符重复定义的错误。为避免这些错误,应使用条件编译来测试有无重复定义。,七、编译预处理,编译预处理: P139 宏定义 文件包含 条件编译 【编译】C编译系统对源程序进行:词法和语法分析,代码生成,优化 .OBJ文件 【编译预处理】编译前对源程序进行一些预加工(改善程序设计环境/模块化设计) 编译预处理命令均以#开头,未尾不加分号 可出现在程序的任何位置,其作用范围:出现点至所在源程序未尾。,七、编译预处理,以“#”开头的一些命令,它通知编译系统:在进行正式编译前应当先进行一些前期工作(即编译预处理)。,目前,C语言的编译预处理功能主要有如下一些: 1)文件包含,使用命令:#include。 2)宏定义,使用命令:#define、#undef。 3)条件编译,使用命令:#if、#ifdef、#ifndef、#else、#endif 4)提供行号信息,使用命令:#line。 5)编译杂注,使用命令:#progma。 6)错误信息,使用命令:#error。,编译预处理中,应用最多的是对宏的处理。它允许程序员使用define定义并应用宏名字书写C语言程序,同时也指示编译器在正式编译前通过宏替换,使程序能按照C语言的语法进行编译。,1 字符串宏定义及其基本格式,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); 以及: return (2.0* PI* RADIUS); 和 return (PI *RADIUS* RADIUS); 使用宏定义可以提高可理解性。 (2) 易修改性好。,定义符号常量,【例】 #define M 3 #define N (M+1) #define NN N*N/2 main() clrscr(); printf(“NN=%d,“,NN); printf(“5*NN=%dn“,5*NN); ,结果:NN=8,5*NN=40,【讨论】 如果第二行改为: #define N M+1,结果: NN=6,5*NN=18,2 使用宏需要注意的问题,定义符号常量,【例】 #define OK 1 main() printf(“OK=%dn“,OK); ,结果:OK=1,【讨论】 程序中用双括号括起来的字符串中的字符即使与宏名相同,也不进行替换。,3 撤销已定义的宏,用命令undef可以撤销已定义的宏。如: #define OK 1 #undef OK 在#undef命令行之后的范围,OK不再代表1。,4、带参数的宏定义 格式 #define 宏名(参数表) 宏体,【例】 #define PI 3.14159 #define s(r) PI*r*r main() float a=1,sum; sum=s(a); printf(“r=%.0f,s=%fn“,a,sum); ,结果: r=1,s=3.141590,带参数的宏定义,【例】 #define PT 5.5 #define s(A) PT*A*A main() int a=1,b=2; printf(“%4.1fn“,s(a+b); ,结果:9.5,【讨论】注意s(a+b)不是函数,它不做任何计算(如果是函数,则s(a+b)为s(3),结果49.5),s(a+b)=5.51212=9.5,带参数的宏定义,【例】选择正确答案 #include “stdio.h“ #define SUM(y) 1+y main( ) int x=2; printf(“%dn“,SUM(5)*x); A) 10 B) 11 C) 12 D) 15,结果:B,对于求平方的宏定义,可以写出4种形式: #define SQUARE(x) x*x /* (a) */ #define SQUARE(x)(x*x) /* (b) */ #define SQUARE(x) (x)*(x) /* (c) */ #define SQUARE(x) (x)*(x) /* (d) */ 到底哪个对呢?下面用几个表达式进行测试:,用表达式a=SQUARE(n+1)测试, 按(a),将替换为a=n+1*n+1。显然结果不对。 按(b),将替换为a=(n+1*n+1),结果与按(a)相同。 按(c),将替换为a=(n+1)*(n+1),结果对。 按(d),将替换为a=(n+1)*(n+1),结果对。,用表达式a=16/SQUARE(2)测试 对剩下的(c)和(d)进行测试。 按 (c) ,将替换为a=16/(2)*(2)=32,显然结果不对。 按 (d) ,将替换为a=16/((2)*(2))=4,结果对。,2、文件包含,#include 标准方式 只按标准方式(系统存放C库函数头文件所在目录)查找所要包含的文件 对TC,默认只在tcinclude目录下查找 #include “ “ 先在源文件所在目录找指定头文件,若无再按标准方式找(更保险),文件包含命令的处理过程,首先寻找所要求包含的文件,如果找到,就用这个文件的全部内容取代当前文件里的这个包含命令行。被替换进来的文件里仍然可以有文件包含等预处理命令行,这些预处理也会被处理。,文件包含示意图,#include #include 源程序area.c (用户编写),头文件stdio.h (系统提供),头文件math.h (系统提供),area.exe (可执行程序),stdio.h math.h area.c,编译/ 连接,第一章例一中,area.c文件本身只有12行,stdio.h有187行, math.h有107行, 实际上stdio.h本身还包括 一个24行的头文件stdarg.h。 “文件包含”是在编译后连接时“包含”进可执行程序的。 比较:area.c 1kb; area.obj 1kb; area.exe 26kb,stdarg.h,stdio.h stdarg.h math.h area.c,3、条件编译,根据条件决定是否编译某一组语句。常用形式:, 如果标识符被定义过* 如果标识符未被定义过 #ifdef 标识符 #ifndef 标识符 程序段1 程序段1 /*编译此程序段*/ #else #else /*#else部分可省略*/ 程序段2 程序段2 /*反之,编译此程序段*/ #endif #endif *此处指标识符用#define等命令定义过。,3、条件编译, #if 表达式 /*如果表达式为真*/ 程序段1 /*编译程序段1*/ #else 程序段2 /否则*编译程序段2*/ #
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 规划建筑方案设计优化(3篇)
- 有害动物防控知识培训课件
- 月子餐实操培训课件
- 福建建筑动画方案设计研究(3篇)
- 网格业务知识培训课件简报
- 2025年学历类自考专业(护理)-康复护理学参考题库含答案解析(5套)
- 2025年学历类自考专业(建筑工程)结构力学(二)-钢结构参考题库含答案解析(5套)
- 湖北省荆州市沙市区沙市中学2026届化学高一上期中考试试题含解析
- 2025年学历类自考专业(建筑工程)建筑材料-建筑材料参考题库含答案解析(5套)
- 2025年学历类自考专业(建筑工程)-流体力学参考题库含答案解析(5套)
- 青马考试题目及答案
- 算力中心计算任务优化方案
- 劳务派遣工作知识培训课件
- 无人机反制设备原理课件
- 北京市2025年普通高中学业水平等级性考试政治试题(解析版)
- 2025年道路运输两类人员安全员考核分享题库及答案
- 中国肺血栓栓塞症诊治、预防和管理指南(2025版)
- 2025年村干部考试试题(含答案)
- 新华书店招聘面试题库全攻略:行业知识、技能与面试技巧
- 工会招聘考试题及答案
- 1.1认识社会生活 教案 2025-2026学年统编版道德与法治八年级上册
评论
0/150
提交评论