关于C中的"static“,编译器是如何实现的?
这是一个彭博社的面试问题。有什么想法吗?
发布于 2011-02-10 04:10:10
[[我假设我们在这里讨论的是变量上下文中的static,因为static函数只是一个编译/链接时的东西,没有运行时的含义。]]
简而言之,它是特定于实现的。编译器可以自由地做它选择的任何事情。
通常(但绝不是排他性的),静态存储在可执行映像的.bss或.data部分中的固定位置。这具有性能优势,因为它们可以通过文字地址访问,而不是指针引用(就像基于堆栈的变量一样)。由于这是二进制文件的一部分,这也意味着当第一次加载可执行文件时,初始值会自动映射到内存中;不需要初始化例程。
发布于 2011-02-10 10:17:38
静态全局变量通常会在编译时分配一个固定的地址。许多操作系统提供0初始化的内存区域,其他操作系统将部分可执行映像映射到预初始化的数据,以及完全未初始化的区域。根据编译器是否能在编译时计算出静态变量的正确初始内容,它可以选择这些内存区域中最合适的一个,如果需要,可以在以后调用任何运行时初始化。例如:
static int x; // needs to be 0 before main() runs
// best way: 0-initialised memory area
static int y = 3; // best way: map/copy area of executable already containing "3"
static int z = time(NULL); // initial value unimportant
// best way: uninitialised memory area
// pre-main() init code注意:例如,将z放入0初始化内存中,然后销毁它并不是很浪费--只是严格来说并不是必须的。某些操作系统可能有单独的区域来存放只读/常数值。
可以根据全局变量创建具有编译时已知初始值的静态局部变量。对于运行时初始化值(只有在C++中是合法的),编译器倾向于(必须?)在第一次进入作用域时初始化它们。这通常是通过为每个包含静态局部变量的作用域设置一个隐式的支持布尔值来协调的:每次输入作用域时,都会查询布尔值,以查看是否需要初始化静态变量。在一些编译器上,这实际上可能是以一种效率较低但线程安全的方式完成的,这样静态局部变量就可以用于单例实例。
编辑:鉴于Lundin的评论(正确地)断言所有C statics必须在main()之前初始化,我写了一些代码来探索这一点:
#include <stdio.h>
#include <time.h>
void f()
{
static int i = time(NULL);
printf("%d\n", i);
}
int main()
{
int i = time(NULL);
printf("%d\n", i);
sleep(2);
f();
}使用GCC的C编译器,我得到了一个致命的编译错误,关于在运行时需要初始化的本地static i。编译为C++ (我的主要语言),这是完全合法的,并且在运行时和进入main()之后进行初始化-这表明我上面的那部分解释只与C++相关。
在生成的对象中简单地标记静态函数,以便链接器在匹配来自其他对象的未解析调用时不会考虑它们。
https://stackoverflow.com/questions/4949882
复制相似问题