单片机c语言的自动变量和静态变量解析

变量的存储类别分为自动、静态、寄存器和外部这四种。其中后两种我们暂不介绍,主要是自动变量和静态变量这两种。
函数中的局部变量,如果不加 static 这个关键字来修饰,都属于自动变量,也叫做动态存储变量。这种存储类别的变量,在调用该函数的时候系统会给他们分配存储空间,在函数调用结束后会自动释放这些存储空间。动态存储变量的关键字是 auto,但是这个关键字是可以省略的,所以我们平时都不用。
那么与动态变量对应的就是静态变量。首先,全局变量均是静态变量,此外,还有一种特殊的局部变量也是静态变量。即我们在定义局部变量时前边加上 static 这个关键字,加上这个关键字的变量就称之为静态局部变量,它的特点是,在整个生存期中只赋一次初值,在第一次执行该函数时,它的值就是给定的那个初值,而之后在该函数所有的执行次数中,它的值都是上一次函数执行结束后的值,即它可以保持前次的执行结果。
有这样一种情况,某个变量只在一个函数中使用,但是我们却想在函数多次调用期间保持住这个变量的值而不丢失,也就是说在该函数的本次调用中该变量值的改变要依赖与上一次调用函数时的值,而不能每次都从初值开始。如果我们使用局部动态变量的话,每次进入函数后上一次的值就丢失了,它每次都从初值开始,如果定义成全局变量的话,又违背了我们上面提到的尽量减少全局变量的使用这条原则,那么此时,局部静态变量就是最好的解决方案了。
比如第六章最后的例程中有一个控制数码管动态扫描显示用的索引变量 i,我们当时就是定义成了全局变量,现在我们就可以改成局部静态变量来试试。
#include
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, 0xff
};
unsigned int cnt = 0;//记录 t0 中断次数
void main(){
unsigned long sec = 0; //记录经过的秒数
ea = 1; //使能总中断
enled = 0; //使能 u3,选择控制数码管
addr3 = 1; //因为需要动态改变 addr0-2 的值,所以不需要再初始化了
tmod = 0x01; //设置 t0 为模式 1
th0 = 0xfc; //为 t0 赋初值 0xfc67,定时 1ms
tl0 = 0x67;
et0 = 1; //使能 t0 中断
tr0 = 1; //启动 t0
while (1){
if (cnt 》= 1000){ //判断 t0 溢出是否达到 1000 次
cnt = 0; //达到 1000 次后计数值清零
sec++; //秒计数自加 1
//以下代码将 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];
}
}
}
/* 定时器 0 中断服务函数 */
void interrupttimer0() interrupt 1{
static unsigned char i = 0; //动态扫描的索引,定义为局部静态变量
th0 = 0xfc; //重新加载初值
tl0 = 0x67;
cnt++; //中断次数计数值加 1
//以下代码完成数码管动态扫描刷新
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,大家可以自己修改程序看一下实际效果是否和理论相符。


储能行业市场呈现大规模发展之势
与可制造性设计相关问题
Intel司睿博表示全球CPU生产几乎不受影响 疫情期间产品按时交付率超过90%
南非航空将出售A340飞机来改善其财务状况
亚信电子最新TSN/EtherCAT与IO-Link技术整体解决方案
单片机c语言的自动变量和静态变量解析
单片机方案开发注意事项及如何挑选PIC单片机进行学习
角速度传感器在扫地机器人避障上的应用
PCIe—Bar空间是怎么生效的
在曲阜市场中,有哪些OLED品牌?
重大进展!全球首个人工智能光电子神经网络问世
USB-C功率传输数据线需要加强保护
电容触控传感技术在智能手机上的应用
KVM延长器、切换器配合使用机房管理远程管控方案
基于可变步长的多通道噪声主动控制方案
一个个原厂官网搜资料要跪了?世强元件电商新版本 解决工程师困扰
美国无人飞行器Parrot AR.Drone2.0 GPS拆解
恩智浦目前唯一采用5nm的汽车芯片厂商,计划明年交付首款样品
fireflyNCC S1烧写工具--常见问题简介
一骑绝尘领先行业 西部数据发布全新企业级存储解决方案新品