任何程序设计都离不开对于数据的处理,一个程序如果没有数据,它就无法工作。数据在计算机内存中的存放情况由数据结构决定。C语言的数据结构是以数据类型出现的,数据类型可分为基本数据类型和复杂数据类型,复杂数据类型由基本数据类型构造而成。C语言中的基本数据类型有char,int,short,long,float和double。对于C51编译器来说,short类型与int类型相同,double类型与float类型相同。
1.char:字符型
char有signed char(带符号数)和unsigned char(无符号数)之分,默认值为signed char。它们的长度均为一个字节,用于存放一个单字节的数据。对于singed char类型数据,其字节中的最高位表示该数据的符号,“0”表示正数,“1”表示负数。负数用补码表示,数值的表示范围是-128~+127;对于unsigned char类型数据,其字节中的所有位均用来表示数据的数值,数值的表示范围是0~255。
2.int:整型
int有signed int和unsigned int之分,默认值为signed int。它们的长度均为两个字节,用于存放一个双字节的数据。signed int是有符号整型数,字节中的最高位表示数据的符号,“0”表示正数,“1”表示负数。数值的表示范围是-32 768~+32 767。unsigned int是无符号整型数据,所能表示的数值范围是0~65 535。
3.long:长整型
long有signed long和unsigned long之分,默认值为signed long。它们的长度均为四个字节。signed long是有符号的长整型数据,其字节中的最高位表示该数据的符号,“0”表示正数,“1”表示负数,数值的表示范围是-2 147 483 648~+2 147 483 647。unsigned long是无符号长整型数据,数值的表示范围是0~4 294 967 295。
4.float:浮点型
float是符合IEEE-754标准的单精度浮点型数据,在十进制数中具有7位有效数字。float类型数据占用四个字节(32位二进制数),在内存中的存放格式如下:
其中,S为符号位,“0”表示正,“1”表示负。E为阶码,占用8位二进制数,存放在两个字节中。注意,阶码E值是以2为底的指数再加上偏移量127,这样处理的目的是为了避免出现负的阶码值,而指数是可正可负的。阶码E的正常取值范围是1~254,从而实际指数的取值范围为-126~+127。M为尾数的小数部分,用23位二进制数表示,存放在三个字节中。尾数的整数部分永远为 1,因此不予保存,但它是隐含存在的。小数点位于隐含的整数位“1”的后面。一个浮点数的数值范围是(-1) S ×2 E-127 ×(1.M)。
例如,浮点数-12.5=0xC1480000,在内存中的存放格式为:
需要指出的是,对于浮点型数据除了有正常数值之外,还可能出现非正常数值。根据IEEE标准,当浮点型数据取以下数值(十六进制数)时即为非正常值:
0xFFFFFFFF 非数(NaN)
0x7F800000 正溢出(+INF)
0xFF800000负溢出(-INF)
另外,由于8051单片机不包括捕获浮点运算错误的中断向量,因此必须由用户自己根据可能出现的错误条件用软件来进行适当处理。
除了以上四种基本数据类型之外,还有以下一些数据类型。
5. * :指针型
指针型数据不同于以上四种基本数据类型,它本身是一个变量,但在这个变量中存放的不是普通数据而是指向另一个数据的地址。指针变量也要占据一定的内存单元,在C51中指针变量的长度一般为 1~3 个字节。指针变量也具有类型,其表示方法是在指针符号“*”的前面冠以数据类型符号,如char*point1表示point1是一个字符型的指针变量;float*point2表示point2是一个浮点型的指针变量。指针变量的类型表示该指针所指向地址中数据的类型。使用指针型变量可以方便地对8051单片机的各部分物理地址直接进行操作。
6.bit:位类型
bit是Keil C51编译器的一种扩充数据类型,利用它可定义一个位变量,但不能定义位指针,也不能定义位数组。
7.sfr:特殊功能寄存器
sfr也是Keil C51编译器的一种扩充数据类型,利用它可以定义8051单片机的所有内部8位特殊功能寄存器。sfr型数据占用一个内存单元,其取值范围是0~255。
8 . sfr16:16位特殊功能寄存器
sfr16占用两个内存单元,取值范围是0~65 535,利用它可以定义8051单片机内部16位特殊功能寄存器。
9.sbit:可寻址位
sbit也是Keil C51编译器的一种扩充数据类型,利用它可以定义8051单片机内部RAM中的可寻址位或特殊功能寄存器中的可寻址位。
例如,采用如下语句:
可以将8051单片机P0口地址定义为80H,将P0.1位定义为FLAG1。
表2-3列出了Keil C51编译器能够识别的数据类型。
表2-3 Keil C51编译器能够识别的数据类型
在C语言程序的表达式或变量赋值运算中,有时会出现运算对象数据不一致的情况,C语言允许任何标准数据类型之间的隐式转换。隐式转换按以下优先级别自动进行:
bit → char → int → long → float signed → unsigned
其中箭头方向仅表示数据类型级别的高低,转换时由低向高进行,而不是数据转换时的顺序。例如,将一个bit(位型)变量赋给一个int(整型)变量时,不需要先将bit型变量转换成char型之后再转换成int型,而是将bit型变量直接转换成int型并完成赋值运算。一般来说,如果有几个不同类型的数据同时参加运算,则先将低级别类型数据转换成高级别类型,再进行运算处理,并且运算结果为高级别类型数据。C语言除了能对数据类型做自动隐式转换之外,还可以采用强制类型转换符“()”对数据类型做显式转换,强制类型转换符“()”的应用将在2.2.5节中介绍。
Keil C51编译器除了能支持以上这些基本数据之外,还能支持复杂的构造类型数据,如结构类型、联合类型等。这些复杂的数据类型将在本书第5章详细讨论。