C51编译器支持的基本数据类型有:位型(bit)、无符号字符(unsigned char)、有符号字符(signed char)、无符号整型(unsigned int)、有符号整型(signed int)、无符号长整型(unsigned long)、有符号长整型(signed long)、浮点(float)、双精度浮点(double),另外C51还提供了一些扩展的数据类型,它们是由C51支持的基本数据类型按一定的规则组合成的数据类型,称之为构造数据类型。C51支持的构造数据类型有:数组、结构、指针、共同体(或者,也称为联合)、枚举等。其实C51支持的构造数据类型与标准C语言是一样的,对构造数据类型的定义、引用以及运算的规则也与标准的C语言相同。
1.数组
数组是相关的同类对象的集合,是一种构造类型的变量。数组中各元素的数据类型必须相同,元素的个数必须固定,数组中的元素按顺序存放,每个元素对应于一个序号(称为下标),各元素按下标存取。数组元素下标的个数由数组的维数确定,一维数组有一个下标,二维数组有两个下标,多维数组以此类推。这里仅仅介绍常用的一维数组。
(1)一维数组的定义。C51数组定义中增加了存储器类型选项,定义的格式如下:
数据类型[存储器类型]数组名[常量表达式];
数据类型指定数组中元素的类型,[存储器类型]选项可指定存放数组的存储器类型,数组名是一个标识符,其后的方括号是数组的标志,方括号内的常量表达式指定数组元素的个数。
例如:在外部RAM中定义一个存放20个学生成绩的数组:
unsigned char xdata student_score[20];
又如在程序存储器中定义一个LED显示的字符型数据表数组:
unsigned char code SEG_TAB[]={0x3f,0x6,0x5b,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x6f};
/*0~9数码管字形表,这里列出了所有数组元素值,常量表达式*/
(2)一维数组的引用。数组必须先定义以后才能引用,只能逐个引用数组中的元素,不能一次引用整个数组。如上面举例中定义了学生成绩的数组student_score,数组元素student_score[i]代表相应学号的学生成绩,可以分别存取和引用。下面的程序是统计80分以上,60分~80分,60分以下的学生人数的程序。
【例4-7】 统计某班学生成绩中80分以上,60分~80分,60分以下人数的程序。
(3)一维数组的初始化。在定义数组时如果给所有的元素赋值,可以不指定数组元素的个数,但数组标志方括号不可省。
在定义数组时只给部分或全部元素赋值,例如:
unsigned char a[5]={1,2,3};/*a[0]=1,a[1]=2,a[2]=3,a[3]=a[4]=0,有5个元素*/
unsigned char a[]={1,2,3}; /*a[0]=1,a[1]=2,a[2]=3,有3个元素*/
定义数组时使全部元素初值为0,例如:
char b[5]=[0,0,0,0,0];或char b[5]={0};
2.结构体的定义与引用
结构是另一种构造类型数据。通过使用结构可以把一些数据类型可能不同的相关变量结合在一起,给它们一个共同的名称,以方便编程。
(1)定义结构类型。定义结构类型的一般形式为:
例如:定义包含年、月、日的结构类型:
(2)定义结构类型变量。
1)定义结构类型以后,再定义这种结构类型的变量。一般形式为:
结构类型名[存储器类型说明]结构变量名表;
如前面已经定义了struct date结构类型,接着可以再定义属于这种结构类型的变量。例如:
struct date birth_day,works_day;
这样就定义了生日、工作日期两个属于date结构的变量,关键词struct不能少。
2)在定义结构类型时同时定义结构变量,一般形式为:
3)直接定义结构类型变量
这种定义方法就是在上一种方法中省去了结构类型名date。
例如:
(3)结构变量的引用。对结构变量的成员只能一个一个引用。引用结构变量成员的方法有两种:
1)用结构变量名引用结构成员,其形式为:
结构变量名.成员名
例如:birth_day.year=1960;
2)用指向结构的指针引用成员,其形式为:(www.xing528.com)
指针变量名->成员名
例如:birth_day->year=1960;
3.联合的定义与引用
联合也称为共用体,联合中的成员是几种不同类型变量,它们共用一个存储区域,任意瞬间只能存取其中的一个变量,即一个变量被修改了,其他变量原来的值也就消失了。
(1)定义联合类型和联合类型变量。联合类型和联合类型变量可以一起定义,也可以像结构那样先定义联合类型,再定义属于这种联合类型的变量。联合类型和变量一起定义的形式为:
如果同一个数据要用不同的表达方式,可以定义为一个联合类型变量。例如:有一个双字节的系统状态字,有时按字节存取,有时按字存取,则可定义下述联合类型变量:
例如:
(2)联合类型变量成员引用。联合类型变量成员的引用方法类似于结构类型变量成员的引用:变量名.成员名
例如:io_status.status_val=0;
io_status.status[0]=0x80;
因为MCS-51系列单片机的最大外部数据存储空间只有64KB,所以应尽量少用或不用构造类型数据。
4.指针
在C语言中,把存放数据的地址称为指针,把存放数据地址的变量称为指针变量。一般的数据变量表示存储单元内容,而指针变量表示存储单元的地址。利用指针变量访问数据对象类似于用DPTR间接寻址一样地方便。
(1)定义指针变量。指针变量也必须先定义后使用,C51指针变量定义的一般形式为:
基类型[存储器类型]*指针变量名表;
1)基类型说明了所定义的指针变量所能指向的数据对象类型(不能指向其他类型)。
2)使用[存储器类型]选项,称为存储器类型指针,只能指向这种存储器类型的变量,保存指针变量的长度为2字节或1字节。缺省[存储器类型]选项的指针变量称为普通指针变量,可以访问任何类型存储器中的数据对象,保存普通指针变量需3字节。
3)*为定义指针变量的标志。
4)指针变量名也是一个标识符,如果定义多个指针变量,变量名之间用逗号分隔。
例如:int*ptr0/*ptr0为普通指针,可指向任何存储空间的整形变量*/
具体到在C51中,不仅有指向一般变量的指针,还有指向各种构造数据类型成员的指针。C51编译器支持“基于存储器”的指针和“通用指针”两种指针类型。
a.基于存储器的指针。基于存储器的指针以存储类型为参量,在编译时确定。用这种指针可以高效地访问指针指向单元的内容。这类指针的长度为1个字节(idata*,data*,pdata*)或2个字节(code*,xdata*)。例如:
char xdata*px;/*px只能指向xdata区的字符变量*/
表示在定义了一个指向在xdata存储空间的字符型变量的指针变量px,注意指针变量名是px,而不是*px。至于指针自身的存放位置是在默认存储区(具体在哪个存储区由存储器模式决定),指针变量px的长度为2个字节(0~0x FFFF)。
b.通用指针。凡是在指针定义时未对指针指向的对象存储空间进行修饰说明的,编译器都使用3个字节的通用指针。一个通用指针可以访问任何变量而不管它在MCS-51哪个存储空间的什么位置。通用指针只在编译和连接/定位时才把存储空间代码和地址填入预留的3个字节中。
通用指针包括3个字节,其中1个字节为存储类型,另2个字节为偏移地址。存储类型决定了对象所占用的MCS-51存储空间,偏移地址指向实际地址。有关通用指针的字节分配、存储类型编码以及通用指针到具体存储空间的定位如表4-6、表4-7和图4-14所示。
表4-6 通用指针的字节分配
表4-7 通用指针的存储器类型编码
注 使用以上存储器类型编码值以外的值可能会导致不可预测的程序动作。
图4-14 通用指针定位到具体存储空间
例如,以xdata类型的0x1030地址为指针的通用指针的字节分配如下:
(2)指针变量的引用。
1)取变量的地址赋给指针变量。C51中的单目运算符&,是取变量地址的运算符,用&可以将变量的地址赋给一个指针变量。
例如,将变量的地址赋给相应指针变量。
2)引用指针变量间接访问所指向的变量。C51中指针运算符*,为单目运算符,也称间接访问运算符,它可以用指针变量间接访问所指向的变量。例如,在1)中已经定义过了ptr0=&x,则*ptr0就是指的变量x。
3)指针变量的加减1。指针变量的加减1是使指针变量指向下一个或上一个变量。所以,指针变量加减1,其步进是加减数据类型的长度。例如:
Ptr0++/*整形变量占据了两个字节,因此,ptr0指针的值是加了2*/
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。