在C中,存储在内存中的静态变量在哪里?假设有两个静态变量,一个是函数局部变量,另一个是全局变量。如何在符号表中保留此条目?请解释一下。
答案 0 :(得分:13)
在 C 中,可以将它们存储在实现认为合适的任何位置。 C标准没有规定实现是如何做的,只是它如何行为。
通常,所有静态存储持续时间变量(函数内的静态函数和函数外的所有变量)都将存储在同一区域中,无论它们是在文件级还是在函数内。
上面括号中的那一点很重要。在函数之外,static
不会像在函数中那样决定变量的存储持续时间。它决定变量是否在当前翻译单元之外可见。 函数外的所有变量都是静态存储持续时间。
并且,关于符号表,这是仅在构建过程中存在的构造。一旦生成了可执行文件,就没有符号(当然排除了调试信息,但这与代码的执行无关)。此时对变量的所有引用几乎肯定都是硬编码的地址或偏移量。
换句话说,编译器会使用名称来确定您所指的变量。
您可以在此处查看有关如何存储变量的示例。考虑以下小C程序:
#include <stdio.h>
int var1;
static int var2;
int main (void) {
int var3;
static int var4;
var1 = 111;
var2 = 222;
var3 = 333;
var4 = 444;
return 0;
}
这将生成以下程序集:
.file "qq.c"
.comm var1,4,4
.local var2
.comm var2,4,4
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $111, var1
movl $222, var2
movl $333, -4(%ebp)
movl $444, var4.1705
movl $0, %eax
leave
ret
.size main, .-main
.local var4.1705
.comm var4.1705,4,4
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
您可以看到var1
,var2
和var4
(静态存储持续时间)都有.comm
行,以将其标记为常用条目,受制于链接器整合。
此外,var2
,var3
和var4
(在当前传输单元之外不可见的)都有.local
行,因此链接器获胜不要用它们来满足其他目标文件中未解析的外部。
并且,通过在链接文件时检查ld --verbose
的输出,您可以看到所有常见条目最终都在.bss
区域中:
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
: : :
}
答案 1 :(得分:1)
不可能推广到每个编译器,但这是最常用的方式。
链接器将为变量添加一块内存,这些变量在加载时初始化但在运行时可修改。所有静态变量都将放在此块中,无论它们是本地还是全局。
答案 2 :(得分:0)
鉴于以下来源:
static int a_static_var = 5;
void foo(void)
{
static int a_static_var = 6;
return;
}
Visual Studio按如下方式编译变量(至少在这个实例中 - 详细信息因编译器而异,取决于选项):
_DATA SEGMENT
_a_static_var DD 05H
?a_static_var@?1??foo@@9@9 DD 06H ; `foo'::`2'::a_static_var
_DATA ENDS
因此,两个静态变量最终都出现在数据段中 - 作用于函数的静态函数的名称被破坏,以至于它不会与不同函数或源文件中的类似变量“匹配”。 / p>
编译器实现可以随意处理这种情况,但总体思路通常是类似的。