专升本C语言课件C08存储属性及预处理.ppt
C程序设计八 存储属性及预处理,八 存储属性及预处理 8.1 变量的存储属性8.1.1变量的作用域变量有两个方面的属性:数据类型和存储类别变量的存储属性指:变量的作用域和生存期。作用域有2种:局部变量:在函数内有效(定义在函数内或形式参数)全局变量:从定义点到文件的结尾有效。(定义在函数外,又称外部变量)注意分析作用域时不涉及程序运行的流程。,以下哪些是局部变量,哪些是全局变量?判断划线语句是否正确。float x=6,y;main()int i;i=x;x=j;int j;fun1(int*p)int a;a=i*2;fun2()int b;b=x+j;,对错错对,八 存储属性及预处理 8.1 变量的存储属性全局变量的作用:(1)可以从函数得到多个返回值。(2)简化形参。,下面程序采用全局变量得到多个值int a,b;main().swap();.swap()int c;c=a;a=b;b=c;,八 存储属性及预处理 8.1 变量的存储属性全局变量的作用:(1)可以从函数得到多个返回值。(2)简化形参。,比较如下的两个程序:采用全局变量可以简化形参。main().fun1(a,b,p);fun2(a,b,p,4);.fun1(int a,int b,int*p).fun2(int a,int b,int*p,int n).fun1(a,b,p);.,int a,int b,int*p;main().fun1();fun2(4);.fun1().fun2(int n).fun1();.,八 存储属性及预处理 8.1 变量的存储属性全局变量的作用:(1)可以从函数得到多个返回值。(2)简化形参。全局变量的缺点:使函数的通用性降低。程序容易出错。,以下的swap函数拿到其他程序中不能用。int a,b;main().swap();.swap()int c;c=a;a=b;b=c;,八 存储属性及预处理 8.1 变量的存储属性全局变量与局部变量同名时,全局变量被屏蔽。,float x=6,y;main()int i;i=x;x=j;int j;fun2()int b,x=5;b=x+j;这时的x是局部变量,八 存储属性及预处理 8.1 变量的存储属性全局变量与局部变量同名时,全局变量被屏蔽。,程序分析:int a=1;main()int a=7,b=5;fun(a+b);printf(%d,%dn,a,b);fun(int b)b=a+b;a=a*2;printf(%d,%dn,a,b);,2,127,5,八 存储属性及预处理 8.1 变量的存储属性全局变量与局部变量同名时,全局变量被屏蔽。,程序分析:int a=1;main()int a=7,b=5;while(b100)b=b*fun(+a);printf(%d,%dn,a,b);fun(int b)b=a+b;a=a*2;return(b);,9,495,八 存储属性及预处理 8.1 变量的存储属性8.1.2变量的生存期变量有2种生存期:动态存储:在函数被调用时分配空间,函数结束时释放。动态存储变量定义时,初值是不确定的值。静态存储:在编译时被赋初值是0,在整个程序运行时一直存在。,静态存储main()fun1();fun1()int a;/*a是动态存储的变量*/fun2()static int b;/*a是静态存储的变量*/b是静态变量,则不管函数fun2有没有被调用,变量b都会在程序一开始运行时就被定义好了。并且初值是0,八 存储属性及预处理 8.1 变量的存储属性8.1.2变量的生存期,main()int i;for(i=1;i=10;i+)fun1();fun2();fun1()int a;fun2()static int b;变量a,b分别被分配空间几次?,a 10次b 1次,八 存储属性及预处理 8.1 变量的存储属性各种变量的生存期外部变量:静态局部变量:动态 局部变量(auto)形参 函数调用时分配,并且 被赋予实参的值。register 寄存器变量 速度较快 静态static 静态局部变量 既是局部变量,又是 静态变量,判断题:(1)只要是局部变量都可以定义为寄存器变量。错,静态局部变量不可以。(2)用register定义100变量,其中有些变量将被分配内存单元。对。(3)静态局部变量定义时自动赋初值为0对(4)外部变量不可以用auto说明存储类型。对。(5)外部变量必然是静态存储的变量。对。(6)程序执行到定义静态变量时,该变量被创建,一直到程序结束。错。程序一开始就已创建。,八 存储属性及预处理 8.1 变量的存储属性各种变量的生存期外部变量:静态局部变量:动态 局部变量(auto)形参 函数调用时分配,并且 被赋予实参的值。register 寄存器变量 速度较快 静态static 静态局部变量 既是局部变量,又是 静态变量,外部变量:定义在函数的外部int x;动态局部变量:定义在函数内部auto int x;或者 int x;形参:void abc(int x,char y)。寄存器变量:定义在函数内部register int x,y,z;静态局部变量:定义在函数内部static int x;,八 存储属性及预处理 8.1 变量的存储属性各种变量的生存期外部变量:静态局部变量:动态 局部变量(auto)形参 函数调用时分配,并且 被赋予实参的值。register 寄存器变量 速度较快 静态static 静态局部变量 既是局部变量,又是 静态变量,以下程序的输出的结果是int x=3;main()int i;for(i=1;ix;i+)incre();incre()static int x=1;x*=x+1;printf(%d,x);A)3 3 B)2 2 C)2 6 D)2 5,C,八 存储属性及预处理 8.1 变量的存储属性8.1.3 扩展外部变量的作用域用extern声明外部变量,可以扩展外部变量的作用域。(1)在一个文件内扩展。在外部变量的定义点之前的函数内,用extern声明外部变量,就可以使用。如extern a,b;或extern int a,b;,如何在main函数中使用外部变量x?main()int a;a=x+4;.int x;fun1().fun2().,extern x;,八 存储属性及预处理 8.1 变量的存储属性8.1.3 扩展外部变量的作用域用extern声明外部变量,可以扩展外部变量的作用域。(1)在一个文件内扩展。(2)在多个文件扩展。一个C程序可以由多个源文件组成,假如两个文件共用一个外部变量x,必须在一个文件内定义,另一个文件内用extern声明。,文件1int x;main().fun1().,文件2extern x;fun3().x+;fun2().,八 存储属性及预处理 8.1 变量的存储属性8.1.3 扩展外部变量的作用域用extern声明外部变量,可以扩展外部变量的作用域。(1)在一个文件内扩展。(2)在多个文件扩展。一个C程序可以由多个源文件组成,假如两个文件共用一个外部变量x,必须在一个文件内定义,另一个文件内用extern声明。(3)限制外部变量只能在本文件使用。定义外部变量时可以用static。这样外部变量就不能被其他文件引用。,文件1static int x;main().fun1().,文件2extern x;fun3().x+;fun2().x不能引用,八 存储属性及预处理 8.1 变量的存储属性8.1.3 扩展外部变量的作用域用extern声明外部变量,可以扩展外部变量的作用域。(1)在一个文件内扩展。(2)在多个文件扩展。一个C程序可以由多个源文件组成,假如两个文件共用一个外部变量x,必须在一个文件内定义,另一个文件内用extern声明。(3)限制外部变量只能在本文件使用。定义外部变量时可以用static。这样外部变量就不能被其他文件引用。,假如一个程序由如下两个文件组成,判断以下使用是否正确?文件1static int y;extern z;extern a;int b;static int x;,文件2static int y;int z;extern a;int b;extern x;,YYNNN,八 存储属性及预处理 8.1 变量的存储属性8.1.3 扩展外部变量的作用域用extern声明外部变量,可以扩展外部变量的作用域。(1)在一个文件内扩展。(2)在多个文件扩展。一个C程序可以由多个源文件组成,假如两个文件共用一个外部变量x,必须在一个文件内定义,另一个文件内用extern声明。(3)限制外部变量只能在本文件使用。定义外部变量时可以用static。这样外部变量就不能被其他文件引用。,变量x和y有什么区别?static int x;main().fun1()static int y;.,x是外部变量,但不能被其他文件引用y是静态局部变量,只能在本函数使用,八 存储属性及预处理 8.2 内部函数与外部函数外部函数:可以被其他文件调用。格式:extern 类型 函数名(形参)或 类型 函数名(形参)内部函数:一个函数只能在本文件中调用。格式:static 类型 函数名(形参)其他文件调用之前需用extern声明文件1 文件2int fun1(int a)extern fun1(int a);.b=fun1(3);,判断题:(1)不加extern定义的函数可以被其他文件调用。(2)一个文件调用其他文件中的函数时要先声明。(3)一个文件用extern声明函数,就可以引用其他文件中的任何函数。(4)一个文件中的各个函数要么都可以被其他文件调用,要么都不可以。,YYNN,八 存储属性及预处理 8.3 宏定义C语言中的一些操作称为编译预处理:宏定义,文件包含,条件编译。编译预处理是在编译之前进行。预处理命令以#开头,一般不加分号。宏定义有2种:(1)不带参数的宏定义#define PI 3.1415926(2)带参数的宏定义#define S(u,v)u*v替换时宏和参数都要进行替换。宏替换时不进行语法分析。,分析结果#define MU(a,b)b-amain()int x=4,y=2;x=MU(y*2,3);y=MU(x,y)*4;printf(%d,y);,在运行之前先要进行宏替换x=3-y*2;y=y-x*4;,八 存储属性及预处理 8.3 宏定义宏的优点:(1)速度比函数快。(2)不受数据类型限制。(3)不受返回值个数限制。宏的缺点:(1)功能有限。(2)源程序变长。(3)容易出错。,分析结果#define swap(a,b)a=a+b;b=a-b;a=a-b;main()int x=4,y=2;float u=2.5,v=-3.3;swap(x,y);/*不受返回值个数限制*/swap(u,v);/*不受数据类型限制*/.,八 存储属性及预处理 8.4 文件包含将另一个源文件的内容包含到本文件中。#include 文件名先在当前目录找,再到存放库函数头文件的目录中查找。#include 仅在存放库函数头文件的目录中查找。,八 存储属性及预处理 8.4 条件编译条件编译是为了加强程序的可移植性。#ifdef 标识符 程序段1#else 程序段2#endif如果之前标识符已被#define定义过,则编译程序段1,否则编译程序段2。,#define computer 0.#ifdef computer#define INTEGER_SIZE 16#else#define INTEGER_SIZE 32#endif,八 存储属性及预处理 8.4 条件编译条件编译的优点是代码较短运行稍快,#ifdef 标识符 程序段1#else 程序段2#endifif(表达式)程序段1else 程序段2两段程序的区别是后者代码较长,八 存储属性及预处理 8.4 条件编译其他形式的条件编译:如果之前标识符没有被#define定义过,则编译程序段1,否则编译程序段2。#ifndef 标识符 程序段1#else 程序段2#endif,#if 表达式 程序段1#else 程序段2#endif如果表达式的值非0,则编译程序段1,否则编译程序段2。,#define LETTER 0.#if LETTER 程序段1#else 程序段2#endif,