静态变量存储在哪里(在C / C ++中)?
静态变量存储在可执行文件的哪个段(.BSS,.DATA等)中,以使它们不会发生名称冲突?
例如:
foo.c: bar.c: static int foo = 1; static int foo = 10; void fooTest() { void barTest() { static int bar = 2; static int bar = 20; foo++; foo++; bar++; bar++; printf("%d,%d", foo, bar); printf("%d, %d", foo, bar); } }
如果我同时编译两个文件并将其链接到重复调用fooTest()和barTest的主文件,则printf语句将独立递增。这是有道理的,因为foo和bar变量是转换单元的本地变量。
但是在哪里分配存储空间?
明确地说,假设我们拥有一个可以以ELF格式输出文件的工具链。因此,我认为可执行文件中必须为这些静态变量保留一些空间。
出于讨论目的,假设我们使用GCC工具链。
解决方案
数据的存储位置将取决于实现。
但是,静态的含义是"内部链接"。因此,该符号在编译单元内部(foo.c,bar.c),并且不能在该编译单元外部引用。因此,不会有名称冲突。
这取决于我们使用的平台和编译器。一些编译器直接存储在代码段中。静态变量始终只能由当前翻译单元访问,并且不会导出名称,因此不会发生名称冲突的原因。
答案很可能取决于编译器,因此我们可能想要编辑问题(我的意思是,即使段的概念也不是ISO C或者ISO C ++所强制要求的)。例如,在Windows上,可执行文件不带有符号名。一个" foo"的偏移量为0x100,另一个可能为0x2B0,并且编译了来自两个转换单元的代码,知道它们" foo"的偏移量。
我不相信会发生冲突。在文件级别(外部函数)使用static会将变量标记为当前编译单元(文件)的本地变量。它在当前文件之外永远不可见,因此不必使用名称。
在函数内部使用静态变量有所不同,变量仅对函数可见,只是变量的值在对该函数的调用之间得以保留。
实际上,static根据其所在位置执行两项不同的操作。但是,在其他情况下,它会限制变量的可见性,以防止名称空间冲突,
话虽如此,我相信它会存储在倾向于初始化变量的DATA中。 BSS最初代表字节集-<something>,其中包含未初始化的变量。
它们都将被独立存储,但是,如果我们想让其他开发人员清楚,则可能需要将它们包装在命名空间中。
在"全局和静态"区域中:)
C ++中有几个内存区域
- 堆
- 免费商店
- 堆
- 全局和静态
- const
请参阅此处以详细了解问题
如前所述,将静态变量存储在数据段或者代码段中。
我们可以确保不会在堆栈或者堆上分配它。
因为static
关键字将变量的范围定义为文件或者函数,所以没有冲突的风险,如果发生冲突,会有编译器/链接器警告我们。
一个很好的例子
静态变量的去向取决于它们是否被初始化为0。 0个初始化的静态数据进入.BSS(以符号开头的块),非0初始化的数据进入.DATA
在编译单元中声明的数据将进入文件输出的.BSS或者.Data。 BSS中的初始化数据,DATA中未初始化的数据。
静态数据和全局数据之间的区别在于文件中包含符号信息。编译器倾向于包含符号信息,但仅这样标记全局信息。
链接器尊重此信息。静态变量的符号信息将被丢弃或者破坏,以便仍可以以某种方式(使用调试或者符号选项)引用静态变量。在两种情况下,编译器都不会受到影响,因为链接器首先解析本地引用。
实际上,变量是元组(存储,范围,类型,地址,值):
storage : where is it stored, for example data, stack, heap... scope : who can see us, for example global, local... type : what is our type, for example int, int*... address : where are we located value : what is our value
本地作用域可能意味着对翻译单元(源文件),功能或者块而言是本地的,具体取决于其定义的位置。为了使变量对多个功能可见,它肯定必须位于DATA或者BSS区域中(分别取决于其是否显式初始化)。然后将其范围限定为源文件中的所有功能或者所有功能。