3.3 常量、变量介绍与演练
3.3.1 常量
1.常量的数据类型
常量是在程序运行过程中不能改变值的量,常量的数据类型主要有整型、浮点型、字符型、字符串型。
(1)整型常量
整型常量可以用十进制、八进制和十六进制表示。二进制形式,虽然是计算机中最终的表示方法,但太长,所以,C语言不提供用二进制表达常数的方法。
用十进制表示,是最常用也是最直观的。例如:7356、-90等。
八进制用数字0开头(注意不是字母o),例如:010、016等。
十六进制以数字0+小写字母x或大写字母X开头),如0x10、0Xf等。注意:十六进制数只能用合法的十六进制数字表示,字母a、b、c、d、e、f既可以大写,也可以小写。
(2)浮点型常量
浮点型常量可分为十进制和指数表示形式。十进制由数字和小数点组成,如0.888、3345.345、0.0等。指数表示形式为[±]数字[.数字]e[±]数字,[]中的内容为可选项,其中,内容根据具体情况可有可无,但其余部分必须有,如125e3,7e9,-3.0e-3。
(3)字符型常量
字符型常量是单引号内的字符,如‘a’、‘d’等,不可以显示的控制字符可以在该字符前面加一个反斜杠“\”组成专用转义字符。常用转义字符如表3-4所示。
表3-4 常用转义字符表
(4)字符串型常量
字符串型常量由双引号内的字符组成,如“test”,“OK”等。当引号内没有字符时,为空字符串。在C语言中,系统在每个字符串的最后自动加入一个字符‘\0’作为字符串的结束标志。请注意字符常量和字符串常量的区别,例如,‘Z’是字符常量,在内存中占一个字节,而“Z”是字符串常量,占两个字节的存储空间,其中一个字节用来存放‘\0’。
2.用宏表示常数
假设要写一个有关圆的计算程序,那么π(3.14159)值会被频繁用到。显然没有理由去改π的值,所以,应该将它当成一个常量对待,那么,是否一遍一遍地写3.14159这一长串的数呢?
必须有个偷懒的方法,并且要提倡这个办法,因为多次写3.14159,难免哪次就写错了。这就用到了宏。宏不仅可以用来代替常数值,还可以用来代替表达式,甚至是代码段。下面只谈其中代替常数值的功能。
宏的语法为
#define 宏名称 宏值
例如,要代替前面说到的π值,应为
#define PAI 3.14159
注意:宏定义不是PICC严格意义上的语句,所以,其行末不用加分号结束。
有了上面的语句,在程序中凡是要用到3.14159的地方都可以使用PAI这个宏来取代。作为一种建议和一种广大程序员共同的习惯,宏名称经常使用全部大写的字母。
3.用const定义常量
常量还可以用const来进行定义,格式为
const 数据类型 常量名 = 常量值;
例如:
const float PAI = 3.14159;
const的作用就是指明这个量(PAI)是常量,而非变量。
常量必须一开始就指定一个值,然后,在以后的代码中,不允许改变PAI的值。
用宏定义#define表示的常量和用const定义的常量有没有区别呢?有的。用#define进行宏定义的时候,只是单纯的替换,不会进行任何检查,如类型、语句结构等,即宏定义常量只是纯粹的替换关系,如#define null 0;编译器在遇到null时总是用0代替null;而const定义的常量具有数据类型,定义数据类型的常量便于编译器进行数据检查,使程序可能出现错误进行排查,所以,用const定义的常量比较安全。另外,用#define定义的常量,不会分配内存空间,每用到一次,都要替换一次,如果这个常量比较大,而且又多次使用,就会占用很大的程序空间。而const定义的常量是放在一个固定地址上的,每次使用时只调用其地址即可。
3.3.2 变量
在程序运行过程中,其值可以被改变的量称为变量。变量有两个要素:一是变量名,变量命名遵循标识符命名规则;二是变量值,在程序运行过程中,变量值存储在内存中。
在PICC中,要求对所有用到的变量必须先定义、后使用,定义一个变量的格式如下:
[存储种类] 数据类型 [存储器类型] 变量名表
在定义格式中,除了数据类型和变量名表是必要的,其他都是可选项。
1.变量的初始化
unsigned int a;
声明了一个整型变量a。但这变量的值的大小是随机的。无法确定一个变量值是常有的事。但出于某种需要,需要事先给一个变量赋初值。为变量赋初值一般用“=”进行赋值,例如:
unsigned int a = 0;
其作用是将0赋予a,让a的值初始化为0。定义多个变量时也一样,例如:
unsigned int a = 0,b= 1;
需要说明,定义一个变量时,如果一个变量的值小于255,一般将其定义为unsigned char类型,最好不要定义为unsigned int类型,因为unsigned char类型只占一个字节,而unsigned int类型则占用2个字节,当然,如果这个变量的值大于255,则不能将其定义为unsigned char类型,只能将其定义为unsigned int类型或其他合适的类型。
2.变量的存储器类型
PIC单片机的存储器主要有程序存储器和数据存储器。
(1)程序存储器
程序存储器只能读,不能写。程序存储器除了代码外,往往还用于存放固定的表格、字形码等不需要在程序中修改的数据。
在PICC中,使用const关键字用来说明存储于程序存储器中的数据,例如:
const char a=10;
(2)数据存储器
PIC单片机的数据存储器RAM较为特殊,是按bank来使用的。不同型号的PIC单片机,其内部RAM的数量各不相同。以PICl6F877A芯片为例,该芯片的所有RAM空间被分为4个bank,即bank0~bank3。
为了使编译器产生最高效的机器码,PICC把单片机中数据寄存器的bank问题交由编程员自己管理,因此,在定义用户变量时,必须自己决定这些变量具体放在哪一个bank中。如果没有特别指明,所定义的变量将被定位在bank0中,例如,下面所定义的这些变量:
unsigned char buffer[32]; bit flag1,flag2;
除了bank0内的变量声明不需特殊处理外,定义在其他bank内的变量前面必须加上相应的bank序号,例如:
bank1 unsigned char buffer[32]; //变量定义在 bank1中 bank2 bit flag1,flag2; //变量定义在 bank2中
PIC16F877A单片机数据寄存器的一个bank大小为128字节,除去前面若干字节的特殊功能寄存器区域,在C语言中某一bank内定义的变量字节总数不能超过可用RAM字节数。如果超过bank容量,在最后连接时会报错。
3.变量的存储种类
此部分内容将在后面介绍函数时进行说明。
3.3.3 常量与变量演练
1.演练3——变量存储类型练习1
(1)实例说明
这个实例主要演练变量定义为const类型和非const类型的区别。
(2)源程序
#include "pic.h" void main() { const unsigned char a=10; unsigned char b ; b=a+1; for(;;); }
(3)程序运行
打开MPLAB IDE软件,建立工程项目,再建立一个名为ch3_3.c的源程序文件,输入上面源程序,进行软件仿真,观察变量的值。
由于a存储在程序存储区,而该存储区的数在程序运行中不能修改,因此,a的值不能进行任何变动,例如,若在程序中加入“a=a+1;”等类似语句,编译时将报错。
该实验程序在所附光盘的ch3\ch3_3文件夹中。
2.演练4——变量存储类型练习2
(1)实例说明
这个实例主要演练变量的定位(bank0~bank3)问题。
(2)源程序
#include "pic.h" void main() { static bank1 char a=1; static bank2 char b=2; for(;;); }
该源程序在所附光盘的ch3\ch3_4文件夹中。
(3)程序运行
打开MPLAB IDE软件,建立工程项目,再建立一个名为ch3_4.c的源程序文件,输入上面源程序,编译的结果如下:
Memory Usage Map: Program ROM $0000 - $003C $003D ( 61) words Program ROM $07FD - $07FF $0003 ( 3) words $0040 ( 64) words total Program ROM Bank 0 RAM $0020 - $0021 $0002 ( 2) bytes Bank 0 RAM $0070 - $0070 $0001 ( 1) bytes $0003 ( 3) bytes total Bank 0 RAM Bank 1 RAM $00A0 - $00A0 $0001 ( 1) bytes total Bank 1 RAM Bank 2 RAM $0110 - $0110 $0001 ( 1) bytes total Bank 2 RAM Program statistics: Total ROM used 64 words (0.8%) Total RAM used 5 bytes (1.4%)
可以看出,在bank1和bank2中,分别有一个字节被变量占用。