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、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题; |
|
来自: happy123god > 《读书笔记及小结》