代码优先:
#include <stdio.h>
void foo()
{
static int bar;
}
int main()
{
bar++;
return 0;
}
编译器(Clang)抱怨:
static.c:10:2: error: use of undeclared identifier 'bar'
static int bar;
中的foo()
语句不应该给bar
静态存储持续时间,这会使它在main函数之前被声明和初始化吗?
答案 0 :(得分:5)
您将变量的范围与存储持续时间混淆。
如C11
标准中所述,章节§6.2.1,标识符范围,
[...]如果声明标识符的声明符或类型说明符 出现在任何块或参数列表之外,标识符具有文件范围,即 终止于翻译单元的末尾。 [...]
和功能(或阻止)范围
[...]如果是声明符或类型说明符 声明标识符出现在块内或参数声明列表中 一个函数定义,标识符有块作用域,它终止于 相关块。 [...]
在您的情况下,bar
的文件范围为foo()
。因此main()
中 。
OTOH,存储持续时间部分,
在没有存储类说明符的情况下声明其标识符的对象
_Thread_local
,可以是外部或内部链接,也可以是存储类 说明符static
,具有静态存储持续时间。它的一生就是整个执行 在程序启动之前,程序及其存储的值只初始化一次。
因此,总而言之,bar
具有静态存储持续时间,但范围仅限于foo()
函数。所以,它是
在
之前声明并初始化main()
函数
(在main()
开始之前,确切地说)但在main()
中不可见且无法访问。
答案 1 :(得分:2)
在函数中将某些内容标记为static
会将其存储重新定位到堆栈之外,并允许其值在多个调用中保持不变。
然而,标记某些内容static
不会改变变量的范围。虽然您当然可以创建一个针对bar
并从main
处理它的指针,但编译器会因为范围界定而将bar
视为未定义main
。