Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2970448
  • 博文数量: 523
  • 博客积分: 11908
  • 博客等级: 上将
  • 技术积分: 5475
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-03 15:50
文章分类

全部博文(523)

文章存档

2019年(3)

2013年(4)

2012年(71)

2011年(78)

2010年(57)

2009年(310)

分类: C/C++

2009-07-16 20:55:11

C语言中static关键字

static 声明的变量在C语言中有两方面的特征:

1、  当它用于函数定义时,或用于代码之外的变量声明时static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响,用这种方式声明的函数或变量只能在声明它们的源文件中访问

源文件名:main.c
#include

unsigned char add_one=1;

unsigned char add_two=2

unsigned char flag;//同变量address,只不过它的链接属性为external

static unsigned char address;//该变量在编译时就被分配空间,地址在SRAM中,如果没初始化,该值被默认初始化为0

全局变量和的存储是放在一块的,初始化的和静态变量在一块区域(add_oneadd_two), 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(flagaddress)。程序结束后由系统释放。

static void zoom_in(void);

int main (void)

{

    return 0

}

static void zoom_in (void)  
{
   
……

}

2、  当它用于代码块内部的变量声明时,static关键字把变量从自动变量修改为静态变量(存储类型改变),但变量的链接属性和作用域不受影响,用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一直存在而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁(这是指存储类型为自动类型的局部变量)

static void zoom_in (void) 
{

static unsigned char add =1;  
     unsigned char s2[] = "abc";
栈上,
     unsigned char *p5 = "123456";p5
在栈上,123456\0在常量区,位于

                                   SRAM

add=2     

……
}

静态变量static在程序执行前就创建了,地址位于SRAM中,值为1(不初始化就为0)。以后不管调用几次,static unsigned char add =1;这条语句不会执行。

第一次调用zoom_in()时

add=2

如果第二次调用zoom_in(),static unsigned char add =1;不会执行,add=2

 

 

低    ->|-----------------|
      | 全局量(所有已初始化量 .data, |
      | 未初始化量 .bss )       |
  堆起始->|-----------------|
      |    堆向高地址增长      |
      |                 |
      |                 |
      |     自由空间        |
      |                 |
      |                 |
      |    栈向低地址增长      |
高 栈起始->|-----------------| 0x045F

 

0x0000

0x0060

0x045F

 

 

其它说明:

 

问题:Static的理解

  关于static变量,请选择下面所有说法正确的内容:

  A、若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;

  B、若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;

  C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;

  D、静态全局变量过大,可那会导致堆栈溢出。

  答案与分析:

  对于AB:根据本篇概述部分的说明b),我们知道,A,B都是正确的。

  对于C:根据本篇概述部分的说明a),我们知道,C是正确的(所谓的函数重入问题,下面会详细阐述)。

  对于D:静态变量放在程序的全局数据区,而不是在堆栈中分配,所以不可能导致堆栈溢出,D是错误的。

  因此,答案是ABC

  3、问题:不可重入函数

  曾经设计过如下一个函数,在代码检视的时候被提醒有bug,因为这个函数是不可重入的,为什么?

unsigned int sum_int( unsigned int base )
{
 unsigned int index;
 static unsigned int sum = 0; // 注意,是static类型的。
 for (index = 1; index <= base; index++)
 {
  sum += index;
 }
 return sum;
}

  答案与分析:

  所谓的函数是可重入的(也可以说是可预测的),即:只要输入数据相同就应产生相同的输出。

  这个函数之所以是不可预测的,就是因为函数中使用了static变量,因为static变量的特征,这样的函数被称为:带“内部器”功能的的函数。因此如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量,这种函数中的static变量,使用原则是,能不用尽量不用。

  将上面的函数修改为可重入的函数很简单,只要将声明sum变量中的static关键字去掉,变量sum即变为一个auto 类型的变量,函数即变为一个可重入的函数。

  当然,有些时候,在函数中是必须要使用static变量的,比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针

 

C++ static的用法:
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值。
静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见。
用法1:函数内部声明的static变量,可作为对象间的一种通信机制
如果一局部变量被声明为static,那么将只有唯一的一个静态分配的对象,它被用于在该函数的所有调用中表示这个变量。这个对象将只在执行线程第一次到达它的定义使初始化。
用法2:局部静态对象
对于局部静态对象,构造函数是在控制线程第一次通过该对象的定义时调用。在程序结束时,局部静态对象的析构函数将按照他们被构造的相反顺序逐一调用,没有规定确切时间。
用法3:静态成员和静态成员函数
如果一个变量是类的一部分,但却不是该类的各个对象的一部分,它就被成为是一个static静态成员。一个static成员只有唯一的一份副本,而不像常 规的非static成员那样在每个对象里各有一份副本。同理,一个需要访问类成员,而不需要针对特定对象去调用的函数,也被称为一个static成员函 数。类的静态成员函数只能访问类的静态成员(变量或函数)。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

阅读(1276) | 评论(0) | 转发(0) |
0

上一篇:register修饰符

下一篇:volatile关键字

给主人留下些什么吧!~~