前言
今天在写单片机程序时,再次接触到static关键字,所以对static的用法进行了整理。static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护。
本文只是初步整理,仅供参考。后期遇到其他用法再做增补。
Static 关键字
静态局部变量
在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。
局部变量我们都知道,静态局部变量是什么呢?
用static修饰的局部变量就是静态局部变量。通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。这就是局部变量的特点所在,但是这个特点有时候会成为我们编程的弊端,限制了我们的程序。static关键字解决的就是这个问题。
比如说,在某个函数体内定义了一个局部变量i并对其初始化(注意:编译器一般不对普通局部变量进行初始化,也就是说它的值在初始时是不确定的,除非对其显式赋值),然后对这个变量进行处理(例如:i++)得到新的i。当我们再次调用这个函数时,我们想用自加后的i,但是由于函数有一次对i进行了重新定义初始化,所以每次调用这个函数,得到的i都是同一个数值,不能实现自加的效果。我在写单片机程序的时候,遇到的就是这个问题,程序如下:
void tm0_isr() interrupt 1 using 1
{
static char i;
TL0 = T1MS; //reload timer0 low byte
TH0 = T1MS >> 8; //reload timer0 high byte
if (count-- == 0) //1ms * 1000 -> 1s
{
count = 2; //reset counter
P2=0xe0;P0=~tube[i];P2=0x00;
P2=0xc0;P0=T_COM[i];P2=0x00;
i++;
if(i==8) i=0;
}
}
这是一个定时器函数,每隔2ms执行此函数,内部8次为一轮循环,所以每次调用此函数,其中的i要自加一次,所以要保证每次i的值都要被保存,不能被初始化,所以只要在 char 的前面加上static关键字即可解决这个问题,这就是 static 的作用所在。(注意:静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。)
static的作用总结起来就是:调用函数结束后,将局部变量的值保护起来,下次再调用其所在函数时,使其不会被初始化。静态局部变量的效果跟全局变量有一拼,但是位于函数体内部,就极有利于程序的模块化了。
再来个例程,就可以完全理解了。
#include <stdio.h>
void fn(void)
{
int n = 10;
printf("n=%d\n", n);
n++;
printf("n++=%d\n", n);
}
void fn_static(void)
{
static int n = 10;
printf("static n=%d\n", n);
n++;
printf("n++=%d\n", n);
}
int main(void)
{
fn();
printf("--------------------\n");
fn_static();
printf("--------------------\n");
fn();
printf("--------------------\n");
fn_static();
return 0;
}
运行结果如下:
n=10
n++=11
--------------------
static n=10
n++=11
--------------------
n=10
n++=11
--------------------
static n=11
n++=12
静态全局变量
全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。
普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。
所以,在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。
静态函数
函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:
- 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
- 不同的文件可以使用相同名字的静态函数,互不影响
非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明
总结
合理运用static对于程序的友好性和可读性有很大的提高。