zoukankan      html  css  js  c++  java
  • static

    static在c里面可以用来修饰变量,也可以用来修饰函数。
    先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不是堆,不要弄混。


    复制代码 代码如下:
    int a ;
    int main()
    {
        int b ;
        int c* = (int *)malloc(sizeof(int));
    }

    a是全局变量,b是栈变量,c是堆变量。
    static对全局变量的修饰,可以认为是限制了只能是本文件引用此变量。有的程序是由好多.c文件构成。彼此可以互相引用变量,但加入static修饰之后,只能被本文件中函数引用此变量。

    static对栈变量的修饰,可以认为栈变量的生命周期延长到程序执行结束时。一般来说,栈变量的生命周期由OS管理,在退栈的过程中,栈变量的生命也就结束了。但加入static修饰之后,变量已经不再存储在栈中,而是和全局变量一起存储。同时,离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。

    static对函数的修饰与对全局变量的修饰相似,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。

    文件a.c


    复制代码 代码如下:
    static int i; //只在a文件中用
    int j;          //在工程里用
    static void init()         //只在a文件中用
    {
    }
    void callme()          //在工程中用
    {
        static int sum;
    }

    上面的全局i变量和init()函数只能用在a.c文件中,全局变量sum的作用域只在callme里。变量j和函数callme()的全局限扩充到整个工程文件。所以可以在下面的b.c中用extern关键字调用。extern告诉编译器这个变量或者函数在其他文件里已经被定义了。

    文件b.c


    复制代码 代码如下:
    extern int j;                    //调用a文件里的
    extern void callme();   //调用a文件里的
    int main()
    {
      ...
    }

    extern的另外用法是当C和C++混合编程时如果c++调用的是c源文件定义的函数或者变量,那么要加extern来告诉编译器用c方式命名函数:

    文件A.cpp调用a.c里面的变量i和函数callme()


    复制代码 代码如下:
    extern "C"  //在c++文件里调用c文件中的变量
    {
       int j;
       void callme();
    }
    int main()
    {
       callme();
    }

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

    全局变量有外部、静态两种存储方式。
    (1)全局变量一般用外部存储方式存储,用保留字extern加以定义。此时,变量的作用域是构成整个程序的所有程序文件,也就是定义的外部变量可供其它程序文件使用。
    使用这样的全局变量一定要非常慎重,一旦产生错误,将波及整个程序。

    (2)如果希望全局变量仅限于本程序文件使用,而其它程序文件中不能引用,这时必须将其存储方式定义为静态存储方式,用保留字static加以定义。此时称为静态外部变量。
    例如,在上例文件filel.c中,如果作这样的定义:
    static int a:
    则变量a的作用域被缩小至本程序文件filel.c,文件file2.c中不能引用。
    值得注意的是对全局变量加static,定义为静态存储方式,并不意味着是静态存储;而不加static,是动态存储。两种形式的全局变量(外部变量)都是静态存储方式,都是编译时分配存储空间,但作用域不同。使用静态外部变量,有利于隔离错误,有利于模块化程序设计。

    (3)全局变量的缺省存储方式是外部存储方式。
    前面章节中的程序没有见到变量的存储类别定义,实际上采用变量的缺省存储方式。对局部变量采用auto方式,对全局变量采用extern方式。这也是至今为止,我们在程序中没有见到auto、extern等的原因。
    至此,我们对变量的存储类别及数据类型进行了全面讨论,在此作个小结。

    1.变量定义的一般形式
    存储类别数据类型变量表;

    2.变量定义的作用
    ①规定了变量的取值范围。
    ②规定了变量进行的运行操作。
    ③规定了变量的作用域。
    ④规定了变量的存储方式。
    ⑤规定了变量占用的存储空间。

    3.局部变量和全局变量
    从作用域角度将变量分为局部变量和全局变量。它们采取的存储类别如下:

    局部变量:
    ①自动变量,即动态局部变量(离开函数,值就消失)。
    ②静态局部变量(离开函数,值仍保留)。
    ③寄存器变量(离开函数,值就消失)。
    ④形式参数可以定义为自动变量或寄存器变量。

    全局变量:
    ①静态外部变量(只限本程序文件使用)。
    ②外部变量(即非静态的外部变量,允许其它程序文件引用)。

    4.动态存储和静态存储
    从变量存在时间可将变量存储分为动态存储和静态存储。静态存储是在整个程序运行时都存在,而动态存储则是在调用函数时临时分配存储单元。

    动态存储:
    ①自动变量(函数内有效)。
    ②寄存器变量(函数内有效)。
    ③形式参数。

    静态存储:
    ①静态局部变量(函数内有效)。
    ②静态外部变量(本程序文件内有效)。
    ③外部变量(整个程序可引用)。

    5.静态存储区和动态存储区
    从变量值存放的位置可将变量存储区分为静态存储区和动态存储区:
    内存中静态存储区:
    ①静态局部变量。
    ②静态外部变量。
    ③外部变量(可被同一程序其它文件引用)。
    内存中动态存储区:自动变量和形式参数。
    CPU中的寄存器:寄存器变量。
    详细出处参考:http://www.jb51.net/article/40521.htm

    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。
    介绍它的第一条也是最重要的一条:隐藏。
    当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。

    下面是a.c的内容


    复制代码 代码如下:
    char a = 'A'; // global variable
    void msg()
    {
        printf("Hello ");
    }

    下面是main.c的内容
    复制代码 代码如下:
    int main(void)
    {   
        extern char a;    // extern variable must be declared before use
        printf("%c ", a);
        (void)msg();
        return 0;
    }

    程序的运行结果是:
    A Hello

    你可能会问:为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。

    如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏


    详细出处参考:http://www.jb51.net/article/40520.htm

  • 相关阅读:
    D. Constructing the Array
    B. Navigation System
    B. Dreamoon Likes Sequences
    A. Linova and Kingdom
    G. Special Permutation
    B. Xenia and Colorful Gems
    Firetrucks Are Red
    java getInstance()的使用
    java 静态代理和动态代理
    java 类加载机制和反射机制
  • 原文地址:https://www.cnblogs.com/yunsicai/p/3254742.html
Copyright © 2011-2022 走看看