单片机应用技术(第4版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.5 C51的数据结构

C51与C语言相同,其数据有常量和变量之分。常量是在程序运行中不能改变值的量,可以是字符、十进制数或十六进制数(用0x表示)。变量是在程序运行过程中不断变化的量。无论是常量还是变量,其数据结构是以数据类型决定的。

2.5.1 C51的常量

常量就是在程序执行过程中不能改变值的量。常量的数据类型有整型、浮点型、字符型、字符串型及位类型。

1.整型常量

整型常量可用十进制、十六进制表示,如果是长整数则在数字后面加L。举例如下。十进制整数:1234,-56;十六进制整数:0x123,-0xFF;长整数:6789L、0xAB12L。

2.浮点型常量

浮点型常量可用十进制和指数两种形式表示。

十进制由数字和小数点组成,整数和小数部分为0可以省略,但小数点不能省略。例如:0.1234,.1234,1234.,0.0等。

指数表示形式为 [±] 数字 [.数字] e [±] 数字。例如:123.4e5,-6e-7等。

3.字符型常量

字符型常量为单引号内的字符,如 ‘e’、‘k’ 等。对于不可显示的控制符,可在该字符前用反斜杠“\”构成转义字符表示。如表2-7所示为一些常用的转义字符。

4.字符串型常量

字符串型常量为双引号内的字符,如“ ABCD” “@#%”等。当双引号内没有字符时,表示空字符串。在C51中字符串常量是作为字符型数组来处理的,在存储字符串时系统会在字符串的尾部加上转义字符“\ 0”作为该字符串的结束符。所以字符串常量“ A”与字符常量 ‘A’ 是不同的。

5.位常量

位常量的值只能取1或0两种。

2.5.2 C51的变量与存储类型

变量是一种在程序执行过程中值不断变化的量。变量在使用之前,必须进行定义,用一个标识符作为变量名并指出它的数据类型和存储模式,以便编译系统为它分配相应的存储单元。C51对变量的定义格式如下:

微课:C51变量的定义

[存储种类] 数据类型 [存储器类型] 变量名表

常用的转义字符如表2-7所示。

表2-7 常用的转义字符表

下面分别介绍变量定义格式中的各项。

1.存储种类

存储种类项为可选项。变量的存储种类有4 种:自动(auto)、外部(extern)、静态(static)和寄存器(register)。如果在定义变量时省略该项,则默认为自动(auto)变量。

自动变量(auto)指被说明的对象放在内存的堆栈中。只有在定义它的函数被调用或是定义它的复合语句被执行时,编译器才为其分配内存空间。当函数调用结束返回时,自动变量所占用的空间就被释放。

外部变量(extern)指在函数外部定义的变量,也称为全局变量。只要一个外部变量被定义后,它就被分配了固定的内存空间,即使函数调用结束返回,其存储空间也不被释放。

静态变量(static)分为内部静态变量和外部静态变量两种。如果希望定义的变量在离开函数后到下次进入函数前变量值保持不变,就需要使用静态变量说明。使用这种类型对变量进行说明后,变量的地址是固定的。

寄存器变量(register)指定将变量放在CPU的寄存器中,程序执行效率最高。

2.数据类型

C语言的数据类型可分为基本数据类型和复杂数据类型,其中复杂数据类型又是由基本数据类型构造而成。C51中的数据类型既包含与C语言中相同的数据类型,也包含其特有的数据类型。

微课:C51中的基本数据类型

(1)char:字符型

字符型数据的长度为一个字节。有signed char (有符号数)和unsigned char (无符号数)两种,默认值为signed char。unsigned char类型数据可以表达的数值范围是0~255; signed char类型数据的最高位表示符号位,“ 0”为正数,“1”为负数。负数用补码表示,其表达的数值范围是-128~+127。

(2)int:整型

整型数据的长度为双字节。有 signed int 和 unsigned int 两种,默认值为 signed int。unsigned int类型数据可以表达的数值范围是0~65 535; signed int类型数据的最高位表示符号位,“0”为正数,“1”为负数,其表达的数值范围是-32 768~+32 767。

(3)long:长整型

长整型数据的长度为4个字节。有signed long和unsigned long 两种,默认值为signed long。unsigned long类型数据可以表达的数值范围是0~4 294 967 295; signed long类型数据的最高位表示符号位,“0”为正数,“1”为负数,其表达的数值范围是-2 147 483 648~+2 147 483 647。

(4)float:浮点型

浮点型数据是指符合IEEE-754标准的单精度浮点型数据,其长度为4个字节。在内存中的存放格式如下。

其中,S表示符号位,“0”为正数,“1”为负数。E为阶码,占8位二进制数。阶码的E值是以2为底的指数再加上偏移量127表示的,其取值范围是1~254。M为尾数的小数部分,用23位二进制数表示,尾数的整数部分永远是“1”,因此被省略,但实际是隐含存在的。一个浮点数的数值可表示为(-1)S×2E-127×(1.M)。

例如,-7.5=0xC0F00000,以下为该数在内存中的格式。

除以上几种基本数据类型外,还有以下一些数据类型。

(5)∗:指针型

指针型数据与前4种数据结构不同的是,它本身就是一个变量,在这个变量中存放的不是数据而是指向另一个数据的地址。C51中的指针变量的长度一般为1~3 B。其变量类型的表示方法是在指针符号“∗”的前面冠以数据类型的符号,如char ∗ point1表示point1是一个字符型的指针变量。

指针型变量的用法与汇编语言中的间接寻址方式类似,表2-8 表示两种语言的对照用法。

表2-8 汇编语言与C语言的对照用法

(6)bit:位类型

位类型是C51编译器的一种扩充数据类型,利用它可以定义一个位变量,但不能定义位指针,也不能定义位数组。它的值只可能为0或1。

(7)sfr:特殊功能寄存器类型

特殊功能寄存器类型也是C51编译器的一种扩充数据类型,利用它可以定义51系列单片机的所有内部8位特殊功能寄存器。sfr型数据占用一个内存单元,取值范围为0~255。例如:sfr P0=0x80,表示定义P0为特殊功能寄存器型数据,且为P0口的内部寄存器,在程序中就可以使用P0=255对P0口的所有引脚置高电平。

(8)sfr16:16位特殊功能寄存器类型

与sfr一样,sfr16是用于定义51系列单片机内部的16位特殊功能寄存器。它占用两个内存单元,取值范围为0~65 535。

(9)sbit:可寻址位类型

可寻址位类型也是C51编译器的一种扩充数据类型,利用它可以访问51系列单片机内部RAM的可寻址位及特殊功能寄存器中的可寻址位。例如:

sfr P1=0x90

sbit P1_1=P1^1

sbit OV=0xD0^2

表2-9列出了C51的所有数据类型。

表2-9 C51的所有数据类型

在C51中,如果出现运算对象的数据类型不一致的情况,按以下优先级(由低到高)顺序自动进行隐式转换。

bit → char → int → long → float → singed → unsigned,转换时由低向高进行。

(10)数组

C51编译器除了能支持以上这些基本数据类型外,还能支持复杂的构造类型,如数组、结构体、联合体等,数组就是一种常用的数据类型。

1)数组定义

在C51中,数组必须先定义后使用。一维数组的定义格式如下:

类型说明符 数组名 [常量表达式];

类型说明符是指数组中的各个数组元素的数据类型;数组名是用户定义的数组标识符;方括号中的常量表达式表示数组元素的个数,也称为数组的长度。

例如:

            int a[10];         / /定义整型数组a,有10个元素
            char ch[20];       / /定义字符数组ch,有20个元素

定义数组时,应注意以下几点:

[1] 数组的类型实际上是指数组元素的取值类型。对于同一个数组,所有元素的数据类型都是相同的。

[2] 数组名的书写规则应符合标识符的书写规定。

[3] 数组名不能与其他变量名相同。

[4] 方括号中常量表达式表示数组元素的个数,如a[5] 表示数组a有5个元素。数组元素的下标从0开始计算,5个元素分别为a[0]、a[1]、a[2]、a[3]、a[4]。

[5] 方括号中的常量表达式不可以是变量,但可以是符号常数或常量表达式。

2)数组元素

数组元素也是一种变量,其标志方法为数组名后跟一个下标。下标表示该数组元素在数组中的顺序号,只能为整型常量或整型表达式。如为小数时,C51编译器将自动取整。定义数组元素的一般形式为:

数组名[下标]

在程序中不能一次引用整个数组,只能逐个使用数组元素。例如,数组a包括10个数组元素,累加10个数组元素之和,必须使用下面的循环语句逐个累加各数组元素:

        int a[10],sum;
        sum=0;
        for (i=0; i<10; i++)sum=sum+a[ i] ;

不能用一个语句累加整个数组,下面的写法是错误的:

      sum=sum+a;

3)数组赋值

结合数组赋值的方法有赋值语句和初始化赋值两种。

[1] 数组赋值语句赋值。在程序执行过程中,可以用赋值语句对数组元素逐个赋值,例如:

      for (i=0; i<10; i++)
          num[ i] =i;

[2] 数组初始化赋值。这种方式在数组定义时给数组元素赋予初值,是在编译阶段进行的,可以减少程序运行时间,提高程序执行效率。初始化赋值的一般形式为:

类型说明符 数组名 [常量表达式] = {值,值,…,值};

其中,在 {} 中的各数据值即为相应数组元素的初值,各值之间用逗号间隔,例如:

          int num[10] = {0,1,2,3,4,5,6,7,8,9};

相当于:

          num[0] =0; num[1] =1; …; num[9] =9;

3.存储器类型

该项为可选项。Keil Cx51编译器完全支持51系列单片机的硬件结构和存储器组织,对每个变量可以定义表2-10中的存储器类型。

表2-10 Keil Cx51编译器所能识别的存储器类型

若在定义变量时省略了存储器类型项,则按编译时使用的存储器模式来确定变量的存储器空间。Keil Cx51编译器的3种存储器模式为SMALL、LARGE和COMPACT,这3种模式对变量的影响如表2-11所示。

表2-11 存储器模式对变量的影响

变量应用举例如下。

        char data var;                      /∗  在data区定义字符型变量var ∗/
        int a=5;                        /∗  定义整型变量a,同时赋初值等于5,变量a
                                          位于由编译器的存储器模式确定的默认存储
                                          区中 ∗/
        char code text[ ] = “ HELLO!” ;     /∗  在code区定义字符串数组 ∗/
        unsigned int xdata time;             /∗  在xdata区定义无符号整型变量time ∗/
        extern float idata x,y,z;           /∗  在idata区定义外部浮点型变量x,y,z ∗/
        char xdata ∗px;                   /∗  指针 px 指向 char 型 xdata 区,指针 px 自身
                                          在默认存储区,指针长度为双字节 ∗/
        char pdata ∗data py;               /∗  指针py 指向 char 型 pdata 区,指针 py 自身
                                          在data区,指针长度为单字节 ∗/
        static bit data port;                 /∗  在data区定义了一个静态位变量port ∗/

        int bdata x;                        /∗  在bdata区定义了一个整型变量x ∗/
        sbit x0=x^0;                     /∗  在bdata区定义了一个位变量x0 ∗/
        sfr P0=0x80;                     /∗  定义特殊功能寄存器名P0 ∗/
        sfr16 T2=0xCC;                  /∗  定义特殊功能寄存器名T2 ∗/