《数据的表示与存储.ppt》由会员分享,可在线阅读,更多相关《数据的表示与存储.ppt(102页珍藏版)》请在三一办公上搜索。
1、,第2章 数据的表示与存储,主要内容,2.1 C语言的数据类型2.2 整型数据2.3 浮点型数据2.4 字符型数据2.5 字符串数据2.6 指针型数据2.7 枚举型数据2.8 符号常量与const限定2.9 使用typedef命名数据类型,数据类型是程序设计语言中描述数据的机制。程序中的每一个数据都有一个确定的数据类型。,数据类型的概念,2.1 C语言的数据类型,为数据规定数据类型的主要目的是:,刻画数据符号所能具有的一组值在这组值上能够进行的相关操作/运算为数据分配多少存储空间(多少个二进位)如何存储数据数据表示值的表示范围,语言提供数据类型的方式提供一些预定义的基本数据类型允许程序设计者使
2、用预定义的数据类型构造(派生)出新的类型为已有数据类型起一个新的类型名字,2.1 C语言的数据类型,2.1 C语言的数据类型,5,6,2.2 整型数据,C语言中的整数类型关键字(数据类型标识),2.2 整型数据,short int longint型数据的存储位数至少为16位long型数据的的存储位数至少为32位,7,C语言中整型数据的特点与表示,带符号整型数据的数值表示范围为-2n-12n-1-1无符号整型数据的数值表示范围为 02n-1,带符号整数采用补码表示,不带符号整数一定采用原码表示,采用n位存储位数时数的表示范围,C标准并没有统一规定int、short和long型数据使 用多少二进位
3、存储,但要求:,2.2 整型数据,8,Turbo C中整数类型及数值表示范围,2.2.1 整型常量,常量是在程序运行过程中其值已知且不能改变的量。从表示形式上看,C语言中有字面常量(直接常量)和符号常量之分。,9,整型字面常量,十进制形式的整型常量,十进制形式的整型常量由、号(号可有可无)和十进制数字构成。例如:100-567+123,2.2.1 整型常量,八进制形式的整型常量 八进制形式的整型常量由+、号和八进制数字、并以数字0开头构成。书写时符号可有可无。例如:0123-076十六进制形式的整型常量 十六进制形式的整型常量由+、号和十六进制数字、并以0 x或0X开头构成。书写时符号可有可无
4、。例如:0 x123-0 xAE,10,2.2.1 整型常量,没有任何类型指示的整型常量的类型其数值在int型数据的表示范围内则为int型,否则为 long型如:12345(int型)32769(long型)如果超出long型数的表示范围,自动进行溢出处理(以Turbo C为例):,11,整型常量数据类型的确定,溢出处理的结果=1溢出数的符号值2n-1溢出数mod 2n-1,如程序中给出的数是2147483649,则:,溢出处理后的值11214748364812147483647,在整型常量后面添加字母u或U,表示按无符号类 型处理与存储。例如:123u(表示unsigned int型)在整型
5、常量后面添加字母l或L,表示按long类型处理与存储。例如:123L(表示long型)u或U与l或L可以组合使用,先后顺序无关紧要。,2.2.1 整型常量,显式地指定整型常量的数据类型,例如:123UL 或 123LU,2.2.2 整型变量,变量是在程序运行期间其值可以改变的量。变量的属性变量的标识(命名)类型值与取值范围初始化(初值)存储引用及作用域,13,变量的名字按C语言的标识符命名规则确定,但需要注意:不能使用关键字作为变量名避免使用保留字作为变量名不宜使用库函数名作变量名不应使用预处理命令标识符作为变量名变量名应该尽量反映变量在程序中的作用与含义因各编译程序允许的变量名的长度不同,为
6、程序 的易移植性,应尽量使用短变量名。变量名中区分大小写字母,14,变量的命名,2.2.2 整型变量,正确的变量名:Sum sum Total_value j k_ _errorno _1_ Int 错误的变量名:123-1-2-3$33 c/s taxrate int正确但不合适的变量名:ifdef printf _ _kcab,15,2.2.2 整型变量,程序中使用的所有变量都必须在函数的开始先声明(declaration)后使用。规定变量先声明后使用有利于及时发现程序中的错误。“声明”是C语言中的一种特殊语句,其特殊性在于:非计算功能语句不能前缀语句标号限定使用位置有定义性与引用性声明之
7、分,16,变量的声明,2.2.2 整型变量,17,变量声明的一般语法形式,其中的“”部分表示可有可无。,2.2.2 整型变量,存储类型 数据类型 变量名1=表达式1,变量名2=表达式2,变量名n=表达式n;,因此,变量声明的简单形式可以是:,数据类型 变量名;,数据类型 变量名1,变量名2,变量名n;,变量声明中的“存储类型”部分决定变量的存储空间位于内存哪个区域,以及该变量的生命周期。可以指定如下4个存储类型关键字:auto 指定存储到堆栈区 static 指定存储到静态数据区 register 指定存储到寄存器 extern 通常用于指出引用外部对象声明,2.2.2 整型变量,声明的变量可
8、被指定存储到3种不同的存储区域中:静态数据区堆栈区寄存器,2.2.2 整型变量,变量声明中的“数据类型”部分指出变量的数据类型。对于整型变量来说可以是书上表2-2中列出的类型关键字之一。例如:int a;unsigned int b;long c;,int x,y,z;,/*定义了3个int型变量 x,y,z*/,unsigned m;,/*定义了1个unsinged int型变量m*/,/*定义了1个int型变量a*/,/*定义了1个unsinged int型变量b*/,/*定义了1个long型变量c*/,在C语言程序中的多个不同位置处都可以声明变量。在不同位置处声明的变量具有不同的作用域、
9、生命期。作用域指程序中的标识符能够被引用的范围 生命期指程序中的标识符从建立到撤消的有 效与存在时间,20,程序中声明变量的位置,2.2.2 整型变量,在编译阶段分配其存储空间生命期是整个程序运行期除特别说明外,其作用域是整个源程序文件,所以也称为文件作用域。例如:int a;/*外部变量声明*/int main(void),21,外部变量,在函数外部声明的变量相对函数而言称之为“外部变量”。这种变量的特点是:,2.2.2 整型变量,在函数内部声明的变量则称之为“局部变量”。可以在函数中的四个不同位置处声明局部变量:在函数体的开始位置在函数的形式参数位置函数中复合语句的开始位置在for循环语句
10、中,22,局部变量,2.2.2 整型变量,只在该函数内有效;具有块作用域;在该函数内的语句可以直接使用它们;在函数被调用执行时才被分配存储空间,而当退出函数时取消其定义。例如:int main(void)int a;,23,2.2.2 整型变量,在函数体开始位置声明的变量的性质:,这种变量是一种作用域更小的局部变量,仅限于该复合语句,对函数的其他部分是不可见、不可存取的。每当执行进入复合语句时才给其中声明的变量分配存储空间,离开复合语句时取消其定义。,int main(void)while(a0)int a;,24,2.2.2 整型变量,复合语句是一对大括号括住的程序块,也称分程序。,在复合语
11、句开始位置声明的变量的性质:,例如:,形式参数变量也是一种局部变量,其性质及其作用域与在函数体的开始部分定义的变量相同。,25,2.2.2 整型变量,在函数的形式参数位置声明的变量称为形式参数变量。,形式参数变量的性质:,int fun(int a,int b),这两种变量的初始化是由系统自动进行的!C编译程序将在编译阶段为其分配存储空间,并将分配的存储空间清0,相当于给这类变量置初值0。,26,变量初始化,2.2.2 整型变量,首次向变量中存值称之为变量的初始化。,外部变量和静态局部变量的初始化,非静态局部变量的初始化,C编译程序仅为这类变量分配存储空间,并不将分配的存储空间清0!此时变量的
12、存储空间中存值是未知的(称为“无定义”值);程序中不应该使用无定义的变量!有3种显式初始化变量的手段:,在声明变量的同时指定初值。语法形式:数据类型 变量名=初始化值;例如:int a=1,b=2,c=3;注意:static型变量和外部变量的初始化值必须为常量或常量表达式(由一个或若干个全部是直接常量或符号常量组成的计算式)。例如:,27,2.2.2 整型变量,#define PI 3.14/*PI 是定义的符号常量名*/static int a=2;static float b=2.35+4.2/PI;,在函数和复合语句中声明的带有初始化值的static型 局部变量仅在编译时对它们初始化一次
13、,但下面的声明是错误的:,static int c=2+5,d=c+3;,因为在 d=c+3 中含有变量名 c,int fun(int a)static int b=1;/*仅在编译时对它初始化一次*/b=b+a;return b;,2.2.2 整型变量,29,auto、register型局部变量的初始化值可以是:常量、符号常量、变量名、函数调用及由它们组成的表达 式。但如果含有变量名,则必须是在这之前已经指 定了初始化值的变量名,不能为函数的形式参数指定初始化值,例如:,int x=-1,y=abs(x),z=x+y;,fun(int p=20,int q=3),2.2.2 整型变量,不允许
14、在定义变量的同时,以如下形式对同一类型的若干个变量置相同的初值:,int x=y=z=100;,但如下方式是允许的:int y,z,x=y=z=100;,2.2.2 整型变量,int a,b;a=-10;b=a+2;,2.2.2 整型变量,通过赋值语句给变量赋初值,定义变量后,可以通过变量名引用变量的值,也可以通过变量名改变变量的值。,例如:,int val;scanf(“%d”,32,2.2.2 整型变量,从外部读入数据存入指定的变量中,可以通过调用scanf()等库函数实现,例如:,假设在16位的C编译程序中,int型变量 val 的存储空间从1000号单元开始,并存储了为-10的值。,3
15、3,2.2.2 整型变量,变量的名字,变量存储空间,变量的值,变量的地址 之间的关系,int main(void)int a,b;b=a;scanf(“%d”,34,声明、使用变量时的常见错误,2.2.2 整型变量,例2.1 使用未初始化变量的值。,int main(void)a=3;int a;,35,2.2.2 整型变量,例2.2 变量声明在动作语句之后。,int main(void)int a,int b;,36,2.2.2 整型变量,例2.3 变量声明语法错误。,不能以如下方式声明带初始化值的变量:int a=b=c=1;如果需要将变量a,b,c都初始化为1,可以写成:int a=1,
16、b=1,c=1;或者 int a,b,c;a=b=c=1;,37,2.2.2 整型变量,例2.4 声明变量的初始化方式错误。,2.3 浮点型数据,浮点数是在计算机中是以二进制指数形式表示的带小数点的十进制数据,C语言中提供了三种不同的浮点数据类型:单精度型(float)双精度型(double)长双精度型(long double)在不同的C编译系统中,它们所占用的存储空间、能表示的数的精度和范围有可能不同。,下表列出了Turbo C中浮点型数据的相关信息,实际上是4种,还有一种:long long double,Turbo C中浮点类型的相关信息,2.3 浮点型数据,float _Complex
17、double _Complexlong double _Complexfloat _Imaginarydouble _Imaginary long double _Imaginary,C99对浮点数据类型的扩充,新增了6种复数类型:,2.3 浮点型数据,2.3.1 浮点数常量,浮点数常量的表示形式 十进制小数形式 十进制小数形式的浮点数常量一般书写形式是:a.b 例如:0.1 0.0 3.0.1 1.2+31.45 000.321 十进制指数形式 十进制指数形式的浮点数常量一般书写形式是:a.bec 或 a.bEc 表示的数值为:a.b10c。,2.3.1 浮点型常量,1.234e8/*表示
18、1.234108*/0.456e9/*表示 0.456109*/,例如:,浮点数常量的类型,大多数C编译程序都规定:程序中浮点数常量在没有任何类型指示的情况下都按double型存储与处理,但允许在浮点数直接量后面加上一个字母F或f,强制将其按单精度浮点数存储与处理,1.5,1.5F,/*按double型存储与处理*/,/*按float型存储与处理*/,2.3.1 浮点型常量,规格化形式的浮点型常量,由于浮点型常量允许指数形式书写,因此一个浮点型常量可以有若干不同的书写形式(值不变)。,规范化形式的浮点型常量的书写是小数点前只有一位非0数字。,例如:,1.23e-2,浮点数在机器内部都是近似表示
19、的,浮点数使用的注意点,像1E6 这样的浮点数虽然值是整数,但仍然是近似 表示的浮点数,2.3.2 浮点型变量,float a,b;double pi=3.14;long double c;引用浮点型变量 float a,b;a=1.0;b=a+10;,声明浮点型变量,浮点型变量的声明格式与整型变量的声明格式相同,只要指定相应的浮点类型关键字即可。,例如:,2.4 字符型数据,字符型数据指的是C语言中表示字母、标点符号、特殊符号之类的数据。本节将学习、掌握字符型数据的表示与使用。,2.4.1 字符集,2.4.2 字符常量,2.4.3 字符型变量,2.4.1 字符集,计算机系统中使用的字符的集合
20、称为“字符集”。C语言主要使用标准ASCII字符集中的符号。,基本的ASCII字符集共有128个字符(96个可打印字 符和32个控制字符),扩充的ASCII字符集共有256个字符,,字符集中的每个字符都用一个唯一的编码,用一个 字节存储,程序中使用与存储的字符实际上是使用字符对应的 编码,2.4.2 字符常量,可显示字符的常量表示,表示方法与形式,一对单引号内放一个字符。,例如:,5 a A;+,因 和字符在C中有特别的用途,所以它们不能直接括在单引号中作为字符常量使用。若必须,则应使用 和 这种形式表示。,与 的表示,2.4.2 字符常量,非打印字符的表示与转义序列,非打印字符不可辨认,无法
21、写成字符直接量。但程序设计中要求使用这类字符的情况很多,如要求换行、退格、走纸等。为满足程序设计的需要,C编译程序提供了表示这类字符的手段转义序列。所谓转义序列,即以一个反斜杠开始,后跟一个约定的字符或所要表示字符的八进制或十六进制编码。,2.4.2 字符常量,例如:n 表示换行 r 表示回车 f 表示换页 使用时只要括上单引号,如:n,常用字符的转义序列 见书上的表2-5,50,常用字符的转义序列,其中:,0,表示字符NULL,ASCII编码为0。因此,0 与数值0等价,在C程序中经常用到。使用时应注意它与空格的区别,空格的编码是32,ddd xhhh,这 是用字符的ASCII编码来表示任意
22、字符的通用方法。,ddd 是要表示字符的八进制形式的ASCII编码,hhh 是要表示字符的十六进制形式的ASCII编码,2.4.2 字符常量,例如:,字母 A 的ASCII编码是65,对应的八进制数为101,十六进制数为41。因此,字母A的字符常量也可写成:101 x41 它们与 A 是等价的。,再如:,空格的编码是32对应的八进制数为40,十六进制数为20。则空格字符的常量可写成:40 x20,2.4.2 字符常量,使用转义序列时应注意:,若在后给出的字符是非约定的字符,例如,没有 k 这样的约定转义序列,此时将忽略,因此字符 常量 k 等价于字符常量 k,在 后可以跟 13 位八进制数字或
23、十六进制数字。但其值不能大于最大的字符编码。否则将出现 Numeric constant too large 的错误。,2.4.2 字符常量,54,2.4.2 字符常量,字符型数据的值与存储字符常量占用内存的一个字节存储其编码值,而不是存储字符本身。程序中任何使用整数的地方都可用对应的字符常量代替。int a;a=5;printf(“a=%dn”,a);事实上C语言中把字符型数据归类到整型数据类型,是按整型数据来处理的。,2.4.3 字符型变量,字符变量的存储字符变量在内存中占用一个字节的存储空间,存储的是字符的编码,并非字符本身。字符变量的声明字符变量说明的一般形式:,char 字符变量名1
24、,字符变量名2,字符变量名n;,char前面可前缀signed关键字,指定按有符号整数处理,其表示范围-128127(缺省时为signed)当在char前面前缀unsigned关键字时,则指定按无符号整数处理,其表示范围 0255,例如:,char c1,c2;char a=a,b=b,c=c;unsigned char d=255;,假定有 char ch;声明语句,要往ch中存储同一个字符有很多方法,如要向ch中存放字符A,则可以:,ch=A;/*直接赋字符常量*/ch=65;/*赋字符A的ASCII编码*/ch=101;/*用字符A的八进制转义序列*/ch=x41;/*用字符A的十六进制
25、转义序列*/ch=a-32;/*a为97减32为65*/,2.4.3 字符型变量,2.4.3 字符型变量,字符变量的初始化,定义字符变量的同时也可以给变量指定初值。,例如:,char a=a,b=b,c=c;,unsigned char d=255;,注意:当给出的初始化值256时,则把给出的初始化值除以256的余数作为变量的初始化值。,例如:,signed char m=258;unsigned char n=258;,则:m和n的值都为2。,另请注意:赋值溢出处理与初始化时的溢出处理是不同的,总是将给出数据的低8位作为变量的值。,例如:,signed char m;unsigned cha
26、r n;m=512;n=512;,赋值后 m 和 n 的值都将为 0。,2.4.3 字符型变量,例1 大小写字母的转换。,main()char c1,c2;c1a;c2b;c1c1-32;c2c2-32;printf(“%c%cn”,c1,c2);,注:,a 的 ASCII 码为 97,比A大32,允许字符数据与整数直接进行算术运算,如例中的:c1c1-32;c2c2-32;,2.4.3 字符型变量,2.4.3 字符型变量,例2 字符数据与整型数据互相赋值。,main()int i;char c;ia;/*相当于把整数97赋给i*/c97;/*相当于把字符a 赋给c*/printf(“%c,%
27、dn”,c,c);printf(“%c,%dn”,i,i);,程序输出:,a,97 a,97,2.5 字符串数据,字符串常量 用双引号括起来的0个或多个字符(任何可表示的字符)就构成了字符串常量。例如:“hello world!”/*字符串中的空格有意义*/“2009.2.25.”“5”“”/*字符串中可以无任何字符*/“The dentist said:”open wide!”“The path is d:newtime”“2389”/*字符串中包含3个字符:23、8和9*/,2.5 字符串数据,字符串常量的存储 当C 编译程序扫描到一个字符串时,将其含有的字符依次存储到一片连续的存储单元中
28、,每个字符占一个字节,存储的是字符的编码,并在最后自动加上一个NULL(0)字符作为字符串的结束符。,例如下列字符串,“This is a string”,在内存中的存储形式是:,2.5 字符串数据,字符常量的界限符为单引号;字符串常量的界限符是双引号。字符型数据可作为整数参与数 值运算;而字符串数据不能。字符型数据的值是整型值;而字符串数据的值是地址量(字符串本身代表字符串的存储起始地址)字符型数据用一个字节存储;而字符串数据需要所包含的字符个数+1个字节存储。字符型数据有对应的字符型变量;而字符串常量没有对应的字符串变量,字符型数据与字符串数据的区别,2.6 指针型数据,2.6.1 地址的
29、概念2.6.2 指针变量声明及初始化,2.6.1 地址的概念,地址是内存单元(通常是一个字节)的唯一编号。地址是何种形式与所用系统有关。,例如:,main()int i;char c;float f;printf(“%p,%p,%p”,&i,&c,&f);,该程序在TC2.0上运行后的输出可能为:FFD6,FFD9,FFDA,在TC系统中的每个地址:,用两个字节存储,用四位十六进制表示,是相对于DS段(数据段)的 相对地址,表示形式是:,i 的地址 DS:FFD6H c的地址 DS:FFD9H f的地址 DS:FFDAH,2.6.1 地址的概念,通过变量的地址及变量的数据类型,可以确定一个变量
30、所占用的存储空间在何处、有多大。,一个变量在主存中占有的空间中的第一个字节的地址即为该变量的存储地址,在C语言中称之为该变量的指针。,在C语言中地址是一种特别的数据类型,称之为指针类型,不同于整型量,二者不相容。,2.6.1 地址的概念,2.6.2 指针变量声明及初始化,既然指针是一种数据类型,那么与其他类型的变量一样,可以声明这种类型的变量,用于存放一个地址量。因此指针类型变量的值是一个内存地址。当一个指针变量存储了某个变量的地址后就称该指针变量指向那个变量。,指针变量声明的一般形式,存储类型数据类型*变量名,这是指针变量本身的存储类型。可指定:auto、register、static、ex
31、tern。用于指出所定义的指针变量存于何处及其生命期。,用于规定指针变量存放何种类型对象的地址,并非所定义的指针变量本身的数据类型。为区别,习惯上将其称为“基类型”。,该“*”是一个指针类型指示符,指出其后的标识符被定义成指针类型,用于存放地址量。,2.6.2 指针变量声明及初始化,存储类型数据类型*变量名,其实,声明中“*”指针类型指示符书写时并不一定要写在变量名的前面,可以写成:,存储类型数据类型*变量名,可以把这种形式理解成:其后的变量名被定义成特定基类型的指针型变量,2.6.2 指针变量声明及初始化,一旦定义了指针变量,便可用它来存放(指向)与其基类型相同的某个对象的地址。如下面的指针
32、变量定义:int*xp;xp总是用于存放int型对象的地址。换句话说,xp中存储的地址所指向的存储区中的内容总按int型数据来解释。若int型数据为16位,并假定分配给一个int 型变量k的存储区域的首地址为2000,如果执行:xp=则有:,分配给指针 变量xp的存储单元,分配给变量k的存储单元,2.6.2 指针变量声明及初始化,2.6.2 指针变量声明及初始化,语言允许定义如下形式的指针变量:void*指针变量名;void型指针变量称之为“无基类型指针变量”,可用来存储任何一种数据类型对象的地址。因此可将其看作为 一种“通用”型的指针变量 但是,如果希望把void型指针变量中存储的地址值赋给
33、另一个具有确定基类型的指针变量时,则应该用强制类型转换运算符将它先转换成相应的基类型指针后再赋给那个指针变量。,例如:,2.6.2 指针变量声明及初始化,main()void*p;int a,*ip;p=,这是一种强制类型转换运算符,表示把p的值的类型强制转换成指向int对象的指针。注意:只是把转换的结果赋给ip,并不改变p本身!,2.6.2 指针变量声明及初始化,指针变量的初始化,语言也允许在定义指针变量的同时给指针变量置初始值。,例如:,int val,x=1085;int*p=,存储类型 基类型*指针变量名=初始化值;,指针变量初始化的要求与限制,给出的“初始化值”必须是与其基类型相同的
34、对象 的地址。,若未给外部(全局)和 static型局部指针变量指定初 始化值,其初值自动为 0(NULL),可直接使用;,非static型局部指针变量在没有指定初值之前其值 无定义(其值不确定),不应直接使用!,初始化值必须为前面已定义过的变量的地址,或在 这之前已被初始化过的指针变量名,且基类型应该 一致。,2.6.2 指针变量声明及初始化,2.6.2 指针变量声明及初始化,空指针变量与无定义指针变量空指针变量 指针变量的值为0,表示指针变量未指向任何对象。int*p=0;或 int*p=NULL;,这是头文件stdio.h 中定义的值为 0的符号常量,地址是一种特殊的数据类型,并非整数,
35、与整数不相容。因此,除数值0之外,不能把一个整数当作地址作指针变量的初始化值。,无定义指针变量 值是不确定的,它可能指向一个不可预知的存储单元,如果通过它访问指向的对象将造成无法预测的后果。,2.7 枚举型数据,枚举是C语言允许的、由用户自行定义的一种数据类型。可以把这种数据类型作为符号常量的一个集合来理解。如果程序中的一个变量仅能取几种可能的值,那么可以把这样的变量定义成为枚举型变量。枚举型变量所能取的值,即是它对应的符号常量集合中符号常量的值。枚举类型实际上是C中的另一种整数类型。因此,C中作为整数处理的数据类型有三种:整型、字符型、枚举型。,2.7.1 定义枚举数据类型,定义枚举类型的一
36、般形式 enum 枚举类型名 枚举常量列表;例如:enum color red,green,yellow;,enum 与枚举类型名(color)组合在一起即为自定义的枚举数据类型的标识。,枚举常量列表,由若干个枚举符号常量组成,它们之间用逗号隔开。,2.7.1 定义枚举数据类型,枚举常量的命名规则按标识符的命名规则由程序设计者自行确定。在同一作用域范围内,所有的枚举常量名不能与变量等其他对象名相同。枚举常量的值 枚举常量表中所列的符号常量名的值不可改变,它们的取值分两种情况:,enum color red,green,yellow,blue;,枚举常量表仅由若干个符号常量名组成,例如:,2.7
37、.1 定义枚举数据类型,则其中的符号常量的值分别为 0、1、2、3。如果其后有更多的枚举项,其值依此顺序递增,枚举常量表中有形如“枚举常量名=常量表达式”的 若干个符号常量名组成。例如:,enum color red,green=5,yellow,blue=1;,则:,red 的值为 0,green 的值为 5,yellow 的值为 6,blue 的值为 1,2.7.2 枚举型变量的声明,声明枚举型变量的一般形式 enum 枚举类型名 变量名列表 例如:enum color col,*cp;,注意:在这之前枚举类型enum color必须已定义过。,另外,C语言还允许在定义枚举类型的同时定义该
38、种枚举型变量。,例如:,enum 枚举项表 枚举变量名1,枚举变量名2,;,C语言允许定义无名枚举类型,enum 枚举类型名枚举项表枚举变量名1,枚举变量名2;,enum red,green,yellow,blue c1,c2;,enum color red,green,yellow,blue c1,c2;,枚举类型数据的使用,无论枚举常量还是变量,编译程序都把它们作 为整型数据来处理。因此它们的值都是整型值。,因枚举项是一个常量,所以在程序中凡是要求使 用整型常数的地方都可以使用枚举常量符号名。,2.7.2 枚举型变量的声明,2.7.2 枚举型变量的声明,枚举项是一个符号常量,不能向它赋值。
39、程序中若 执行:yellow=2;red=0;等赋值语句都是错误的。,大多数C编译程序都要求先把整数值强制转换成枚 举型后再赋给枚举型变量。例如:c1=(enum color)2;,把int数2强制转换成enum color型数据赋给enum color型变量c1,在实际应用中,并不限制某种枚举类型变量只能取 相应枚举项表中所列符号常量的值!,2.8 符号常量与const限定,2.8.1 符号常量2.8.2 const限定,2.8.1 符号常量,C语言程序中可以使用两种常量形式:字面常量(直接常量)与符号常量,字面常量/直接常量以字面书写形式直接表示的常量。如12、1.3、1.3E2、12UL
40、、1.3F、A、“ab”,符号常量是对直接常量规定了一个名字的常量。(用一个标识符来代替一个直接常量),含义清楚,见名知意;书写不易出错;修改时一个常量的值时能做到一改全改。,程序中使用符号常量的好处:,枚举类型定义枚举符号常量预处理宏定义命令#define定义符号常量 const关键字建立符号常量,C语言中有3种手段定义符号常量:,用预处理宏定义命令#define定义符号常量,2.8.1 符号常量,类对象宏定义(不带参数形式,本节介绍)类函数宏定义(带参数形式,在第六章介绍),两种定义形式:,类对象宏定义的一般形式:,#define 宏名 宏主体,功能是用“宏名”代替其后的“宏主体”。,例如
41、:,#define FOUR 2*2,在预处理程序扫描源程序文件时,每遇到一个宏名FOUR,便用宏主体部分指定的字符序列2*2替换掉FOUR,替换过程称为“宏展开”。,2.8.1 符号常量,即要定义的符号常量名按标识符的规则命名,任意的字符序列,是宏名所要代表的对象,#include#define price 30/*price代表30*/int main(void)int number,money;number=10;money=price*number;printf(“price%d a book,%d books cost$%d!n”,price,number,money);,例2.6,
42、若预处理之前的源程序文件内容如下:,2.8.1 符号常量,int main(void)int number,money;number=10;money=30*number;printf(“price%d a book,%d books cost$%d.n”,30,number,money);,经预处理程序处理后的结果:,stdio.h的内容插在此处,替换掉#include,注意:包含在字符串常量中的宏名和位于注解行中的宏名不被替换!,2.8.1 符号常量,宏定义命令语法必须以#号开头;,#define 宏名 宏主体,预处理命令行可插入在源程序文件中的任何行中,但必须在使用它们的位置之前定义,否
43、则不被替换,float PI=3.14;#define PI 3.1/*PI的作用域从该点开始*/int main(void)printf(“%fn”,PI);,这个PI将不被替换!,2.8.1 符号常量,预处理命令的作用域是从该行所在位置起到它所在 的源程序文件的末尾。但可用#undef 预处理命令 取消前面定义过的某个宏名的定义:,#undef 宏名,#define SIZE 100 int main(void)int table SIZE;#undef SIZE/*从该点起,宏名SIZE不再有效*/,2.8.1 符号常量,宏定义命令是C编译系统的预处理程序命令,并不是 C语言语句,所以不
44、要以分号“;”结束。否则将分号 作为常量的一部分;,预处理程序允许在一个类对象宏定义命令行中使用 先前已定义过的宏名,所有的宏名(符号常量)的名字不能相同。,新行(回车换行符)字符作为行结束符。,2.8.1 符号常量,#define UP 2#define DN(2+UP)#define HI DN/2int main(void)float area;area=(UP+DN)*HI)/2;,area=(2+(2+2)*(2+2)/2)/2;,2.8.1 符号常量,宏展开工作是在内存中进行的,因此,并不改变源文件本身,程序设计者也不能直接见到宏展开后的结果形式。某些C编译系统提供专用工具,用以查
45、看宏展开后的结果形式。若上例存放在 file.c 中,则可在命令行上打入如下命令:cpp-P-file.c/*P为大写*/将产生宏展开后的结果文件 file.I。相关内容请查阅所用C编译系统的用户手册。,2.8.1 符号常量,2.8.2 const限定,const限定是C语言本身的语言成分,用它限定的标识符的值不能被修改。,即定义不能改变的变量与符号常量。,const int a=10;/*定义了一个不能被修改的变量a*/int const a=10;/*定义了一个符号常量a*/,定义只读型的变量与符号常量,例如:,定义指向const型对象的指针,即定义不能通过这样的指针间接修改指向对象的值。
46、,例如:,int a=5,b=6;const int*p=,对于本例,则不能执行*p=10;这样的操作。*p 即为 a,*p=10;等价于 a=10;,注意:这里的指针变量p本身并非const型,是可以改变的!,2.8.2 const限定,2.8.2 const限定,定义指针变量及指针变量所指向的对象都是只 读的指针变量,例如:,const int*const p=,注意:通常const只是限定对标识符直接赋值操作,并不阻止通过其他方式来修改其限定的对象的值。例如下面的操作是允许的:,const int a=2;int*p;p=(int*),2.9 使用 typedef 命名数据类型,type
47、def 的功能是为目前已有的任一数据类型标识规定一个新的名字。typedef声明的一般形式typedef 原数据类型标识 新数据类型标识;例如:typedef int INTEGER;这以后,程序中便可用INTEGER来声明int型的数据对象,使用INTEGER就相当于使用int。INTEGER i,p;/*等价于 int i,*p;*/,2.9 使用typedef命名数据类型,命名的新名只是原名的一个别名,并不是建立一个新的数据类型;新名和老名同时存在并有效;用新名和老名定义的对象具有相同的性质和效果,关于typedef声明的几个基本概念,2.9 使用typedef命名数据类型,简化一些比较
48、复杂的类型标识符的书写 enum color red,green yellow;typedefenum colorCOLOR;也可以直接写成:typedef enum colorred,green,yellow COLOR;,利用typedef命名新类型名的主要目的,这以后就可以直接用COLOR来定义enum color型的变量。,例如:,COLOR a,b,c;,如对于enum red,green yellow a,b,c;这样的无名枚举类型,只能在定义类型的同时定义相应的枚举型变量。但可以利用typedef功能为这样的无名枚举类型规定一个类型名,然后用它来定义相应的枚举型变量。,利用typ
49、edef功能可以实现声明无名构造数据 类型的对象,例如:,typedef enum red,green yellow name;name x,y,z;,这是无名枚举类型定义,这是为无名枚举类型规定的新名字,定义无名枚举类型的变量 x,y,z,2.9 使用typedef命名数据类型,2.9 使用typedef命名数据类型,typedef char*string;,#define string char*,则对于程序中的 string name,sign;这样的声明语句,其效果是什么?,请思考:,若程序中有如下定义:,若程序中有如下定义:,则对于程序中的 string name,sign;这样的宏调用,其效果是什么?,