当我们声明静态变量时,编译器实际上做了什么?

时间:2015-06-01 19:29:00

标签: c static-variables

我想了解实际情况,编译器如何处理静态变量。与自动变量不同,静态变量的值即使在块结束后仍然存在,但编译器实际上如何处理它?<​​/ p>

4 个答案:

答案 0 :(得分:9)

与堆栈上的局部变量不同,静态变量保存在特殊的数据段中。静态变量所属的段取决于它们是否初始化为0。 0初始化的静态数据在 .BSS (由符号开始的块)中,非0初始化数据在 .DATA 中。

如果您想了解更多关于可执行文件中不同细分的内容,this维基百科条目是一个很好的起点。我还强烈推荐Randal E. Bryant和David R. O&#39; Hallaron在计算机系统:程序员的视角中的第7章。

我在这里描述了一个特定的场景。您需要考虑到,从一个体系结构到另一个体系结构,从一个操作系统到另一个体系结构,细节会有所不同,依此类推。但是,可执行文件的总体布局仍然如所描述的那样。确实令人兴奋!

修改

作者恳请我澄清:

  

将0初始化变量划分为.bss和   非0初始化为.data?

.BSS 部分计算机系统:程序员的观点中的第7.4节:

  

此部分不占用目标文件中的实际空间;它只是   占位符。目标文件格式区分初始化   和未初始化的空间效率变量:未初始化   变量不必占用对象中的任何实际磁盘空间   文件。

而且,来自Wikipedia

  

通常只存储 .BSS 部分的长度,但不存储数据   在目标文件中。程序加载器分配并初始化   加载程序时bss部分的内存。

总结一下:它是一种节省记忆的机制。

答案 1 :(得分:5)

典型的C编译器生成的汇编输出可以创建四个&#34;部分&#34;记忆链接器/加载器通常将标记有相同部分的各种项目组合在一起,因为它将程序加载到存储器中。最常见的部分是:

&#34; text&#34;:这是实际的程序代码。它被认为是只读的(某些机器上的链接器/加载器可能会将它放在ROM中)。

&#34; data&#34;:这只是RAM的分配区域,从可执行文件复制初始值。加载器将分配内存,然后复制其初始内容。

&#34; bss&#34;:与数据相同,但初始化为零。

&#34; stack&#34;:简单地由加载程序为其程序堆栈分配。

全局和静态变量放在&#34;数据&#34;和&#34; bss&#34;,因此有一生的程序生命。但是,静态变量不会将它们的名称放在符号表中,因此它们不能像全局变量一样在外部链接。变量的可见性和生命周期是完全不同的概念:C语法混淆了两者。

&#34;自动&#34;变量通常在程序执行期间在堆栈上分配(但如果它们非常大,则可以在堆上分配它们)。它们只存在于堆栈框架内。

答案 2 :(得分:2)

static变量是范围有限的全局变量。 @user3386109

  1. static /全局变量存在于程序的生命周期内。
  2. static / global在程序启动时初始化为:

    一个。如果没有明确初始化:到位模式0 B.否则使用明确的值double x = 1.23;

  3. static变量范围仅限于

    一个。如果在函数:文件范围之外定义,则只有文件中的代码可以&#34;参见&#34;变量。
    B.如果在函数内定义:块范围:只有块内的代码可以&#34;参见&#34;变量。

  4. 除非较低的范围定义另一个具有相同名称的变量,否则其范围内只有一个static变量的实例。编译器&#34;知道&#34;首先使用最近的范围访问哪个相同的命名变量。即使在函数内部,也不会重新创建或重新初始化。

  5. 注意:对于多个线程,其他注意事项适用 - 未显示。

    static int fred = 11;
    int sally = 21;
    
    void foo2(void) {
      static int fred = 31;
      int sally = 41;
      printf("static %d non-static %d\n", fred++, sally++);
      {
        printf("static %d non-static %d\n", fred++, sally++);
        {
          static int fred = 51;
          int sally = 61;
          printf("static %d non-static %d\n", fred++, sally++);
        }
      }
    }
    
    int main(void) {
      printf("static %d non-static %d\n", fred++, sally++);
      foo2();
      printf("static %d non-static %d\n", fred++, sally++);
      foo2();
      return 0;
    }
    

    输出

    static 11 non-static 21
    static 31 non-static 41
    static 32 non-static 42
    static 51 non-static 61
    static 12 non-static 22
    static 33 non-static 41
    static 34 non-static 42
    static 52 non-static 61
    

答案 3 :(得分:1)

此代码:

void function()
{
    static int var = 6;

    // Make something with this variable
    var++;
}

在内部与此类似:

int only_the_compiler_knows_this_actual_name = 6;

void function()
{
    // Make something with the variable
    only_the_compiler_knows_this_actual_name++;
}

换句话说,它是一种“全局”变量,但其名称不会与任何其他全局变量冲突。