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

我想知道实际内容是什么,编译器如何处理静态变量。 与自动变量不同,静态变量的值即使在块结束后仍然存在,但编译器实际上如何处理这个?

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

如果您想了解有关可执行文件中不同段的更多信息, 这个维基百科条目是一个很好的起点。 我还强烈推荐Randal E. Bryant和David R. O’Hallaron在“ 计算机系统:程序员的视角”中的第7章。

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

编辑:

作者恳请我澄清:

将0初始化变量划分为.bss和非0初始化为.data是什么意思?

计算机系统的 7.4节:程序员.BSS部分的看法

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

并且,来自维基百科 :

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

总结一下:它是一种节省内存的机制。

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

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

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

“bss”:与数据相同,但初始化为零。

“stack”:简单地由加载程序为其程序堆栈分配。

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

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

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

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

    A.如果没有显式初始化:到位模式0
    B.否则要显示double x = 1.23;的显式值double x = 1.23;

  3. static变量范围要么限制为

    A.如果在函数外定义:文件范围,只有文件中的代码可以“看到”变量。
    B.如果在函数内定义:块作用域:只有块内的代码可以“看到”变量。

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

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

 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 

这段代码:

 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++; } 

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