• 静态变量和全局变量 zz


    转自: http://blog.csdn.net/tiantangniao232/archive/2007/10/23/1838709.aspx

    先看一小段程序:

    #include<iostream>
    using namespace std;

    int nG = 1;
    void Fun( )
    {
        
    static gg = 2;
        int local  
    = gg;
    }

    int main( )
    {                                      ----------------1
        
    static int a = 3;
        
    int b = nG;
        
    int c = a;
        Fun( );
        
    static oo = 4;
        c 
    = oo;
        
    return 0;    
    }
         我们所关心的是这些变量如 nG  gg  a  等等在内存中的分布如何?它们都紧挨着放在一块?还是各有个的存储

        为了解决上述问题,首先提出第一个问题?
        Fun()中的局部静态变量 gg 在多次调用Fun()后(比如2次 )的值是多少?你肯定毫无犹豫地答到:  2
    我如果问为什么?你可能毫无犹豫的答道:局部静态变量 gg  只是在第一次进入函数时被初始化。
      变量 gg 真的是在第一次进入 函数时才被初始化的吗??!! 
     我们可以单步调试跟踪一下,你会发现调试时会直接跳过  static  gg = 2;这一行。
     因此我说变量 gg 在进入Fun函数之前就已经存在了,你信吗?
     我们可以将断点插在  1  处 ,调试  Alt  + 8 进入底层的汇编代码

    12:       static int a = 3;               //对应着main函数中的声明,此时EBP = 0x0012FFC0
    13:       int b = nG;
    00404BB8   mov         eax,[nG (00476f90)]   //这两句给 b  赋值 ,可以发现全局变量 nG 的地址是:0x00476F90
    00404BBD   mov         dword ptr [ebp-4],eax // b 的地址是 0x0012FFBC
    14:       int c = a;
    00404BC0   mov         ecx,dword ptr [nG+8 (00476f98)]  //这两句是给 a赋值,可以发现局部静态变量a的地址是
    00404BC6   mov         dword ptr [ebp-8],ecx                     // 0x00476F98,c的地址是:0x0012FFB8
    15:       Fun( );
    00404BC9   call        @ILT+790(Fun) (0040131b)   --------看下面 Fun的汇编代码
    16:       static oo = 4;
    17:       c = oo;
    00404BCE   mov         edx,dword ptr [nG+0Ch (00476f9c)]  //局部静态变量 oo的地址是 0x00476F9c
    00404BD4   mov         dword ptr [ebp-8],edx
    18:       return 0;
    00404BD7   xor         eax,eax
    19:   }

    Fun的汇编代码:
    7:        static gg = 2;
    8:       int  local = gg;
    004051B8   mov         eax,[nG+4 (00476f94)]//这两句在给local赋值,可以发现 局部静态变量 gg的地址是
    004051BD   mov         [nG (00476f90)],eax     0x00476F94
    9:    }
     由上述可以发现 变量 nG  gg  a  oo它们几个的内存地址很相近
    0x00476F90:-----------------nG的地址
    0x00476F94:-----------------gg的地址
    0x00476F98:-----------------a   的地址
    0x00476F9C:----------------oo的地址
    我们可以发现这些全局变量和静态变量的内存地址,是在一块的。
    总结:
      我们通常都说main函数是程序的入口点,所以就很容易造成一种误解。认为程序一运行就进入了main,这是
    不对的。既然main是函数,是函数就得被调用了才能执行。那么是谁调用了main函数呢?
      通过调用堆栈我们发现,在main函数前还有一个函数:mainCRTStartup()。这个函数通常被称为启动代码,
      由他对程序在进入main函数之前进行初始化(如加载动态链接库分配资源等等),毕竟程序的正常运行不是
    仅仅依靠小小的main就行的。当然初始化过程中包含对全局变量和静态变量的内存分配。这里的全局变量可能好理解,但是静态变量就有点难理解了。比如Fun中的 gg 他是一个局部静态变量啊 为什么会在进入main函数之前就被初始化啦。这就是静态变量的特性,这就是通常我们为什么说静态变量的生命周期,和整个程序的生命周期是一样的。
     下面简要的说一下本程序的运行流程:
      首先由启动代码完成一些必要资源的加载,和全局变量、静态变量(你程序中的所有静态变量,包括局部的)
      初始化,分配内存单元。
      进入main函数,首先进行的操作是在栈上分配一块内存单元,用来分配函数中的局部变量(除了静态变量)和
      参数的压栈以及函数地址的压栈。也就是说上面的main中的局部非静态变量 b  和   c就分配在此 内存块中,它   会在main函数返回后释放。
       同理在进入Fun函数时,首先也会在栈上分配一块内存单元,用来分配Fun函数中的局部变量(除了静态变       量)和参数的压栈以及函数地址的压栈。比如Fun中的local就分配在此段内存块中,它会在Fun函数返回以后
       被释放。
        最后return 0返回,释放分给main函数的内存块,main函数结束以后由mainCRTStartup( )完成全局变量和
       静态变量的释放,毕竟是由它调用mian函数的。
      最后再强调一下,Fun中的局部静态变量不是第一次进入Fun时被初始化的,而是在进入main函数之前就已经
      被初始化了。
  • 相关阅读:
    项目1:即时标记
    每天一个小程序—0000题(python图像处理)
    每天一个小程序—0004题(统计单词出现次数)
    每天一个小程序—第0001题(uuid模块)
    python实现八皇后问题
    2018/01/05——时间会改变一切!
    HDU 6249 Alice’s Stamps(dp)
    51nod 1422 沙拉酱前缀
    【转】DSP动态内存分配函数的使用
    优秀人的博客
  • 原文地址:https://www.cnblogs.com/avril/p/1855878.html
Copyright © 2020-2023  润新知