#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;
}
答案 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
,它在其他地方定义。