变量的存储类别分为自动、静态、寄存器和外部这四种。其中后两种我们暂不介绍,主要是自动变量和静态变量这两种。
函数中的局部变量,如果不加 static 这个关键字来修饰,都属于自动变量,也叫做动态存储变量。这种存储类别的变量,在调用该函数的时候系统会给他们分配存储空间,在函数调用结束后会自动释放这些存储空间。动态存储变量的关键字是 auto,但是这个关键字是可以省略的,所以我们平时都不用。
那么与动态变量对应的就是静态变量。首先,全局变量均是静态变量,此外,还有一种特殊的局部变量也是静态变量。即我们在定义局部变量时前边加上 static 这个关键字,加上这个关键字的变量就称之为静态局部变量,它的特点是,在整个生存期中只赋一次初值,在第一次执行该函数时,它的值就是给定的那个初值,而之后在该函数所有的执行次数中,它的值都是上一次函数执行结束后的值,即它可以保持前次的执行结果。
有这样一种情况,某个变量只在一个函数中使用,但是我们却想在函数多次调用期间保持住这个变量的值而不丢失,也就是说在该函数的本次调用中该变量值的改变要依赖与上一次调用函数时的值,而不能每次都从初值开始。如果我们使用局部动态变量的话,每次进入函数后上一次的值就丢失了,它每次都从初值开始,如果定义成全局变量的话,又违背了我们上面提到的尽量减少全局变量的使用这条原则,那么此时,局部静态变量就是最好的解决方案了。
比如第六章最后的例程中有一个控制数码管动态扫描显示用的索引变量 i,我们当时就是定义成了全局变量,现在我们就可以改成局部静态变量来试试。
- #include <reg52.h>
-
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
-
- unsigned char code LedChar[] = {
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char LedBuff[6] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
- };
- unsigned int cnt = 0;
-
- void main(){
- unsigned long sec = 0;
-
-
- EA = 1;
- ENLED = 0;
- ADDR3 = 1;
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
-
- while (1){
- if (cnt >= 1000){
- cnt = 0;
- sec++;
-
-
- LedBuff[0] = LedChar[sec%10];
- LedBuff[1] = LedChar[sec/10%10];
- LedBuff[2] = LedChar[sec/100%10];
- LedBuff[3] = LedChar[sec/1000%10];
- LedBuff[4] = LedChar[sec/10000%10];
- LedBuff[5] = LedChar[sec/100000%10];
- }
- }
- }
-
- void InterruptTimer0() interrupt 1{
- static unsigned char i = 0;
- TH0 = 0xFC;
- TL0 = 0x67;
- cnt++;
-
-
- P0 = 0xFF;
- switch (i){
- case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
- case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
- case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
- case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
- case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;
- default: break;
- }
- }
大家注意看程序中中断函数里的局部变量 i,我们为其加上了 static 关键字来修饰,就成为了静态局部变量。它的初始化 i = 0 操作只进行一次,程序执行代码中会进行 i++等操作,那么下次再进入中断函数的时候,i 会保持上次中断函数执行完毕后的值。如果去掉 static 这个关键字,那么每次进入中断函数后,i 都会被初始化成 0,大家可以自己修改程序看一下实际效果是否和理论相符。