在函数内部声明静态变量作为extern有什么用?

时间:2012-03-13 14:37:13

标签: c

#include <stdio.h>

static i = 5;

int main()
{
extern int i;
printf("%d\n",i);
return 0;
}

有人可以提供任何用例来在函数块中声明静态变量为extern吗?

为什么不允许这样做?

int main()
{
static i = 5;
extern int i;
printf("%d\n",i);
return 0;
}

2 个答案:

答案 0 :(得分:8)

当您需要访问驻留在另一个转换单元中的变量时,这非常有用,而不会全局暴露外部变量(出于某些原因,例如名称冲突,或者变量不应该可以直接访问,因此使用static来限制其范围,但是TU的标题仍然需要访问权限。

举个例子,假设我们有一个翻译单元foo.c,它包含:

//foo.c
static int i = 0;

i不应在foo.c之外更改或直接访问,但foo.h需要访问i内联函数,但i }不应该使用foo.h向任何翻译单元公开,因此我们可以在功能级别使用extern,仅在IncI范围内公开它,内联函数需要使用i

//foo.h
inline void IncI(int val)
{
    extern int i;
    i += val;
}

你的第二个例子是'不允许',因为编译器认为你试图将两个不同的变量绑定到同一个符号名称,即:它在本地范围创建static i,但搜索{{1}在全局范围内,但找不到它,因为extern int i在函数范围内。一个更聪明的编译器只会修复与static i的链接,无论这是否遵循我不知道的标准。


既然我有一个C standards document来工作(我知道羞耻......),我们可以看到官方立场是什么(在C99中):

  

6.2.2标识符的链接

     

第3节:

     

如果对象或函数的文件范围标识符的声明包含storageclass   说明符静态,标识符具有内部链接。

     

第4节:

     

对于使用存储类说明符extern声明的标识符   可以看到该标识符的先前声明的范围,   如果事先声明指定内部或外部联系,则   后面声明中标识符的链接与   在先前声明中指定的联系。如果没有事先声明   可见,或者如果先前的声明指定没有链接,那么   标识符有外部链接。

因此,因为static i将导致内部链接,static将把该链接带入当前范围。还有一个脚注说明这可能会导致隐藏变量:

  

23)如6.2.1所述,后面的声明可能会隐藏先前的声明。

答案 1 :(得分:0)

在第二种情况下,您告诉编译器您有一个静态(本地)变量i和另一个(全局)变量i,它在其他地方定义。