分享

C语言中的static , extern关键字

 happy123god 2012-03-07
                               C语言中的static , extern关键字

   看了《POINTER ON C》中对C语言中extern , static关键字的介绍,萌发了对此小小总结一下的冲动。
看了几个网页,觉得对其总结的不是很全面。更觉得有必要在这个地方整理,mark下了。
    
    在这之前,不得不先说下作用域,链接属性,存储类型

1. 作用域(scope):当变量在程序的某个部分被声明时,它只有在程序的一定区域才能被访问。
                有文件作用域,函数作用域,代码块作用域和原型作用域。
   1.1  代码块作用域 :位于一对花括号之间的所有语句称为一个代码块。任何在代码块的开始位置
            声明的标识符都具有“代码块作用域”。
  1.2  文件作用域:任何在所有代码块之外声明的标志符都具有文件作用域,表示这些标志符从他们
                    的声明处直到它所在的源文件结尾处都是可以访问的。
   1.3  原型作用域:只适用在函数原型中声明的参数名。
   1.4  函数作用域:作用域在函数里面的,只是适用于语句标签,要求函数中所有的语句标签必须唯一。

2. 链接属性
   当组成一个程序的各个源文件分别被编译之后,所有的目标文件以及那些从一个或多个函数库中引用
的函数链接在一起,形成可执行程序。标识的链接属性决定如何处理在不同文件中出现的标识符。
   链接属性一共有3种—— external (外部),internal (内部)和none(无)。没有链接属性的标识
符总是被当作单独的的个体,也就是说该标识符的多个声明被当作独立不同的实体。属于internal链接
属性的标识符在同一个源文件内的所有声明都指同一个实体,但位于不同源文件的多个声明则分属不同
的实体。最后,属于external链接属性的标识符不论声明多少次,位于几个源文件都表示同一个实体。

3. 存储类型
   变量的存储类型是指存储变量值的内存类型。变量的存储类型决定变量何时创建,何时销毁以及它的
值将保持多久。有三个地方可以用于存储变量:普通内存,运行时堆栈,硬件寄存器。凡是在任何代码
块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存。静态变量在程序运行之前创建,
在程序的整个执行期间始终存在。
   在代码块内部声明的变量的缺省存储类型为auto .它存储与堆栈中。在程序执行到声明自动变量的
代码块时,自动变量才被创建,当程序的执行流离开该代码块时,这些自动变量自行销毁。
   关键字register可以用于自动变量的声明,提示他们应该存储于机器的硬件寄存器而不是内存中。
寄存器变量的创建和销毁时间和自动变量相同,但它需要一些额外的工作。


static , extern 用于修饰变量 :
1. static如果修饰的是代码块之外的变量,即静态全局变量,此变量的作用域为文件作用域,存储在
全局数据区,链接属性为internal。 也就是说,只有在全局静态变量的源文件中才能访问(使用)
此变量。此变量的生命周期是程序运行的整个过程。链接时,链接器在本源文件中查找其声明。

A、该变量在全局数据区分配内存。 
B、初始化:如果不显式初始化,那么将被隐式初始化为0。 
C、访变量只在本源文件可见,严格的讲应该为定义之处开始到本文件结束。  

使一个变量只在源文件中全局使用有时是必要的。 
第一, 不必担心另外源文件使用它的名字,该名字在源文件中是唯一的。 
第二, 源文件的全局变量不能被其他源文件所用,不能被其他的源文件所修改,保证变量的值是可靠的。 

如果我们要在其他文件里面访问全局静态变量,我们可以定义对应的set 和 get接口(类似C++),将
对应的set 和 get接口定义为全局的函数。

2. static如果修饰的是代码块内的变量,即静态局部变量。此变量的作用域为代码块作用域,存储在
全局数据区,链接属性为internal。函数被多次调用时,实际上访问的是同一块内存区。对于需要在
函数内部保存状态,以备下次函数调用时使用的情况,可以使用static局部变量。

3. extern一般是用来修饰代码块之外的变量,即外部变量。此类变量的作用域为文件作用域,存储在
全局存储区。生命周期为程序运行的整个过程。链接属性为external。也就是说,在定义和声明(直接
声明,或者通过#include包含此变量声明的头文件的方式间接声明)的文件中都可以访问。

   
   当static用来修饰局部变量时,它就改变了局部变量的存放位置,将其由原来的栈中存放改为全局静态
储存区,但是没有改变变量的作用域,还是局限在局部的{}里。   (局部变量)
   当static用来修饰全局变量时,它就改变了全局变量的作用域,使其不能被别的程序extern,限制在了
当前文件里,但是没有改变其存放位置,还是在全局静态储存区。(“还是全局的”)


static , extern 用于修饰函数 : 
1、静态函数(注意与类的静态成员函数区别) 
   函数的定义和声明默认情况下在整个程序中是extern的,有时候可能需要使某个函数只在一个源文件中有效,
不能被其他源文件所用,这时在函数前面加上static. 
定义:在函数的返回类型前加上static关键字,函数即被定义成静态函数。 
特点: 
  A、静态函数只能在本源文件中使用(这是与普通函数区别) 
 
第一, 它允许其他源文件建立并使用同名的函数,而不相互冲突 
第二, 声明为静态的函数不能被其他源文件所调用,因为它的名字不能得到, 

    B、注意:在文件作用域下声明的inline函数默认为static类型。 

2、全局函数
   如果你定义的函数,是要在多处调用,特别是中间件层定义,提供给上层使用的情况,
此时你需要定义全局函数,并且在头文件中对该全局函数进行声明(extern void A())。


3. 关于extern的补充
   在cpp程序文件中用到c的库函数时用extern,标明对函数声明,不用C++编译器去
修饰,而用C编译器。



在编译阶段,编译器遇到一个变量的时候,先看是否有此变量的声明。如果没有,则提示编译
错误,找不到这样的标识。如果找到了,则编译通过。
1.由于静态变量作用域是在本源文件,所以一般不需要声明。找到的一般就是其定义了。
2.对于外部变量或函数。编译通过后,在链接过程中,链接器会在整个工程里面查找
  是否有此变量或函数的定义。如果没有,则链接失败。否则,链接成功。

static法则:
    A、若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
    B、若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
    C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题; 


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多