您好!欢迎来到信盈达产学合作协同育人平台|校企合作|嵌入式培训|解决方案|

登录 注册 微信快速登录

扫一扫看效果 关闭

好文章,欢迎分享给朋友

SongLee

12-10 10:25    浏览1536

static关键字

这个关键字前面也有提到,它的作用是强大的。要对static关键字深入了解,首先需要掌握标准C程序的组成。

标准C程序一直由下列部分组成:

  1)正文段——CPU执行的机器指令部分,也就是你的程序。一个程序只有一个副本;只读,这是为了防止程序由于意外事故而修改自身指令;

  2)初始化数据段(数据段)——在程序中所有赋了初值的全局变量,存放在这里。

  3)非初始化数据段(bss段)——在程序中没有初始化的全局变量;内核将此段初始化为0。注意:只有全局变量被分配到数据段中。

  4)栈——增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回地址;环境信息)。这句很关键,常常有笔试题会问到什么东西放到栈里面就足以说明。

  5)堆——动态存储分配。


在嵌入式C语言当中,它有三个作用:


   作用一:在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。


   这样定义的变量称为局部静态变量:在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。也就是上面的作用一中提到的在函数体内定义的变量。除了类型符外,若不加其它关键字修饰,默认都是局部变量。

比如以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void test1(void)
{

   unsigned char a;

   static unsigned char b;

   …

   a++;

   b++;

}

   在这个例子中,变量a是局部变量,变量b为局部静态变量。作用一说明了局部静态变量b的特性:在函数体,一个被声明为静态的变量(也就是局部静态变量)在这一函数被调用过程中维持其值不变。这句话什么意思呢?

   若是连续两次调用上面的函数test1:

1
2
3
4
5
6
7
8
9
10
11
12
void main(void)
{

  …

  test1();

  test1();

  …

}

   然后使程序暂停下来,读取a和b的值,你会发现,a=1,b=2。怎么回事呢,每次调用test1函数,局部变量a都会重新初始化为0x00;然后执行a++;而局部静态变量在调用过程中却能维持其值不变。

   通常利用这个特性可以统计一个函数被调用的次数。

   声明函数的一个局部变量,并设为static类型,作为一个计数器,这样函数每次被调用的时候就可以进行计数。这是统计函数被调用次数的最好的办法,因为这个变量是和函数息息相关的,而函数可能在多个不同的地方被调用,所以从调用者的角度来统计比较困难。

   代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void count();
int main()
{
   int i;
   for (i = 1; i <= 3; i++)

   {
       count();

   {
    return 0;
}
void count()
{
   static num = 0;
   num++;
   printf(" I have been called %d",num,"times/n");
}

   输出结果为:

   I have been called 1 times.

   I have been called 2 times.

   I have been called 3 times.


   作用二:在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

   

   这样定义的变量也称为全局静态变量:在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。也就是上述作用二中提到的在模块内(但在函数体外)声明的静态变量。

   定义全局静态变量的好处:

       <1>不会被其他文件所访问,修改,是一个本地的局部变量。

       <2>其他文件中可以使用相同名字的变量,不会发生冲突。


   全局变量的详细特性,注意作用域,可以和局部静态变量相比较:


       1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

       2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

       3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。


       当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。


   作用三:在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

   

   这样定义的函数也成为静态函数:在函数的返回类型前加上关键字static,函数就被定义成为静态函数。函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

   定义静态函数的好处:

       <1> 其他文件中可以定义相同名字的函数,不会发生冲突

       <2> 静态函数不能被其他文件所用。它定义一个本地的函数。

   这里我一直强调数据和函数的本地化,这对于程序的结构甚至优化都有巨大的好处,更大的作用是,本地化的数据和函数能给人传递很多有用的信息,能约束数据和函数的作用范围。在C++的对象和类中非常注重的私有和公共数据/函数其实就是本地和全局数据/函数的扩展,这也从侧面反应了本地化数据/函数的优势。



评论0 0
评论
内容加载中……,请稍候!

手指长按二维码,快速关注

给TA留言
留言
返回
评论