翻译单元中的`static`定义和`extern声明`的顺序

Uch*_*chi 6 c static extern

我无法理解为什么这不起作用.

extern int i;

int main()
{
  printf(" %d ", i);  
}

static int i =3;
Run Code Online (Sandbox Code Playgroud)

此外,这不起作用:

extern int i;

static int i =3;

int main()
{
  printf(" %d ", i);  
}
Run Code Online (Sandbox Code Playgroud)

但是如果staticextern declaration它工作之前定义了变量:

static int i =3;

extern int i;

int main()
{
  printf(" %d ", i);  
}
Run Code Online (Sandbox Code Playgroud)

正如我所知道的extern int i那样,i它存在于其他地方,在这里它看起来如何(int i)

但是,其他地方意味着:

1)也许,稍后在same翻译单元中指出global variable.

2)也许,在一些other翻译单位.

我认为即使(1)将范围static int i = 3限制i在当前定义的翻译单位,这也是有效的.

是不是static int i =3 global(我的意思是至少它在翻译单元中可见),即使它的翻译单元的范围有限?那么为什么编译器无法找到呢?

当我编译前两个版本时,我得到以下编译时错误:

 error: static declaration of ‘i’ follows non-static declaration
 note: previous declaration of ‘i’ was here
Run Code Online (Sandbox Code Playgroud)

我无法理解此错误消息.此外,为什么它抱怨它作为一个静态declaration不是它definition也?

Yu *_*Hao 6

C11 6.2.2 标识符的链接第4节

对于在范围内使用存储类说明符extern声明的标识符,其中该标识符的先前声明是可见的,31)如果先前声明指定内部或外部链接,则后面声明中标识符的链接与在先前声明中指定的联系.如果没有先前声明可见,或者先前声明未指定链接,则标识符具有外部链接.

所以第二个声明将遵循第一个,回到你的例子,第一个和第二个例子i将有一个extern存储类.编译器认为这是一个错误.

而在第3个例子中,i将是static因为static首先显示.那应该没问题.

并且,在C11的第7节中6.2.2 标识符的链接

如果在翻译单元内,同一标识符同时出现内部和外部链接,则行为未定义.

所以最好不要与这两个声明相同的变量static,并extern在相同的翻译单元.