zoukankan      html  css  js  c++  java
  • 静态变量与全局变量的区别

    main()

    {

    while(1)

    {

       static b=1;

       a=2;

       b++;

       a++;

    }

    }

    我们所理解的静态变量b,只知道它在上面的函数内部只初始化一次,其实是个假像 ,我要表达的是,事实上b初始化的值,不是在循环体完成的.继续下看.

    while(1)

    {

       static b=1;

       a=2;

       b++;

       a++;

    }

    注意这一句:

    static b=1;为什么我们循环体无限循环,b 他只会赋一次值呢,从C上面是看不出来的.

       经过我反汇编发现,

    static b=1; 根本不在循环体中.可以想像,程序被译成目标机器的时候是这个样子

       while(1)

    {

       //static b=1;   这句没有!

       a=2;

       b++;

       a++;

    }

    那么b是什么时候赋的值呢,是编译的时候就确定了。。就是说,编译的时候,就给b初始化好了!

    类似,我们定义全局变量,如果不赋值,编译器给他赋上0.如果定义了值,就在编译的时候就确定下来了,这个值是编译器根据我们的语句赋给它的.而不程序中指令赋给它的!

         那么这个 a,b变量都在哪呢,他们呆在所谓的静态存储区(后面有介绍),物理上整个程序中任意代码都能访问到这片区域,说明他们在存储上是一样的.但是a,b区别又在哪呢,就是对他们的引用,编译器,允许你任何地方,函数中调用a,而b,不行,他有局部作用域,比如你在一个函数中声明了静态变量b,那只能在这函数中调用b.如果在其它的地方调用它,编译器会报错.这就是逻辑上的控制,而实际上,"物理"上是允许程序在任意地方访问b变量,但是编译器哥哥不会让你访问.

               那什么又叫静态存储区呢,我个人认为就是这是安全区域,不会随便被别的变量替掉.分给你的就是你的,不会被别人给占了.

               谈到这里我们顺便提一下,我们其它函数的局部变量存在内存中的位置,局部变量存放在栈中,栈是一片特殊内存区域,多个变量可能共享使用这片区域,这里我们就可以看到一个问题,既然共享使用,假如我们声明一个局部变量,如果不赋初值,这个变量所在栈中的位置,这个位置包含的值,是随机的,是上次别的变量留下来的值.

    静态变量的类型说明符是static。 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量,例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。对于自动变量,它属于动态存储方式。 但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。由此看来,一个变量可由static进行再说明,并改变其原有的存储方式。

    目录

    静态局部变量定义

    静态局部变量特点

    静态全局变量定义

    静态变量与自动变量与内存的关系

    静态变量赋值的问题


    bk.view.catalog.start();nslog.set("catalogshow",1);

    静态局部变量定义


      在局部变量的说明前再加上static说明符就构成静态局部变量。

      例如:

      static int a,b;

      static float array[5]={1,2,3,4,5};

    静态局部变量特点


      静态局部变量属于静态存储方式,它具有以下特点:

      (1)静态局部变量在函数内定义,但不象自动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。

      (2)静态局部变量的生存期虽然为整个源程序,但是其作用域仍与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。

      (3)允许对构造类静态局部量赋初值。若未赋以初值,则由系统自动赋以0值。

      (4)对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。 根据静态局部变量的特点, 可以看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用,因此仍以采用局部静态变量为宜。

      给读者一个简单直白的例子(区别静态局部变量和动态局部变量):

      int fun(int n)

      {

      static int f=1; /*请注意这行的修改*/ 这是 static 结果:

      

      

      

    f=f*n;

      return(f);

      }

      int main()

      {

      int i;

      for(i=1;i<=5;i++)

      printf("%d!=%d ",i,fun(i));

      }

      =========================================================

      int fun(int n)

      {

      int f=1; /*请注意这行的修改*/ 结果是:

      

      

      

    f=f*n;

      return(f);

      }

      int main()

      {

      int i;

      for(i=1;i<=5;i++)

      printf("%d!=%d ",i,fun(i));

      }

      ————————————————————————————————————————————————————————————————


    静态全局变量定义


      全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。应予以注意。

    静态变量与自动变量与内存的关系


      1.分配给全局变量的内存,一直到程序运行结束时才释放。

      2.对于在程序块中申明的变量,在块的入口处对其分配内存,在块退出时释放内存,则这种变量为自动变量。一直到程序结束时才释放内存的为静态变量,也称为全局变量。

      静态变量的存活期

      除范围之外,变量还有存活期,在这一期间变量能够保持它们的值。在应用程序的存活期内一直保持模块级变量和公用变量的值。但是,对于 Dim 声明的局部变量以及声明局部变量的过程,仅当过程在执行时这些局部变量才存在。通常,当一个过程执行完毕,它的局部变量的值就已经不存在,而且变量所占据的内存也被释放。当下一次执行该过程时,它的所有局部变量将重新初始化。

      但可将局部变量定义成静态的,从而保留变量的值。在过程内部用 Static 关键字声明一个或多个变量,其用法和 Dim 语句完全一样:

      Static Depth

      例如,下面的函数将存储在静态变量 Accumulate 中的以前的运营总值与一个新值相加,以计算运营总值。

      Function RunningTotal (num)

      Static ApplesSold

      ApplesSold = ApplesSold + num

      RunningTotal = ApplesSold

      End Function

      如果用 Dim 而不用 Static 声明 ApplesSold,则以前的累计值不会通过调用函数保留下来,函数只会简单地返回调用它的那个相同值。

      在模块的声明段声明 ApplesSold,并使它成为模块级变量,由此也会收到同样效果。但是,这种方法一旦改变变量的范围,过程就不再对变量排他性存取。由于其它过程也可以访问和改变变量的值,所以运营总值也许不可靠,代码将更难于维护。

      声明所有的局部变量为静态变量

      为了使过程中所有的局部变量为静态变量,可在过程头的起始处加上 Static 关键字。例如:

      Static Function RunningTotal (num)

      这就使过程中的所有局部变量都变为静态,无论它们是用 Static、Dim 或 Private 声明的还是隐式声明的。可以将 Static 放在任何 Sub 或 Funtion 过程头的前面,包括事件过程和声明为 Private 的过程。

    静态变量赋值的问题


      请比较一下两个递归函数调用自己(即运行f1(f1())或f2(f2()))时的的运行结果。

      int f1()

      {

      static int n=0;//这里声明静态局部变量n,如果不是第一次使用本函数,则此句不会执行(因为n 是已经存在着的,并且保留着上一次使用后的数据。)

      printf("%d ",++n);

      }

      =============================

      int f2()

      {

      static int n;//

      n=0;//对n重新赋值为0;

      printf("%d ",++n);

      }

    static 声明的变量在C语言中有两方面的特征:
      1)、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。
      2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
    Tips:
      A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
      B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
      C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;
             D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)
             E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。
    函数前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
    扩展分析:术语static有着不寻常的历史.起初,在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量。随后,static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字,所以仍使用static关键字来表示这第二种含义。最后,C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数(与Java中此关键字的含义相同)。
    全局变量、静态全局变量、静态局部变量和局部变量的区别变量可以分为:全局变量、静态全局变量、静态局部变量和局部变量。
               按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
               按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。 
      从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
      static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
      static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
      static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
             static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
               全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。

  • 相关阅读:
    微信jssdk录音功能开发记录
    前端自动化 模块化开发
    git常用命令
    RESTful
    web前端和SEO优化
    论get和post的区别。。
    Mac 用pecl安装PHP扩展失败
    git
    fullPage.js 的使用
    正则表达式
  • 原文地址:https://www.cnblogs.com/liuliu-NoGirl/p/4086328.html
Copyright © 2011-2022 走看看