我估计以前可能已经回答了这个问题。如果有,请标记为副本!
我无法理解extern
对局部变量(或局部函数!)的意义。我似乎无法看到它在功能上与static
局部变量有何不同......例如:
int foo(void) {
extern int i;
return i++;
}
int bar(void) {
static int i;
return i++;
}
AFAICT,foo
和bar
是相同的。根据C99规范的差异是i
中的foo
与i
中的bar
相比应该具有外部链接。也就是说,我想不出任何方式来利用外部链接 - 因为它是一个局部变量,它不能在foo
之外访问,更不用说在文件之外了。
我确定我在这里遗漏了什么 - 它是什么?
感谢所有指出我在extern
和static
上遗漏了类型的人。你是对的。作为SO的常见回答者,我现在明白了在这种疏忽之后投票的挫败感令人沮丧。
答案 0 :(得分:1)
int foo() {
extern i;
return i++;
}
在这里,您可以检测解释器以查看i
在某个外部块中的某处声明,并将此对象与之前声明过的对象i
连接起来 - 在您的情况下,在文件范围内。
在第二种情况下,您告诉解释器将变量i
存储在一个永久存储器中,该存储器在执行时都可用,并且它是函数的本地存储器。
连接算法在ISO {98} paragraph 6.2.2--Linkage of identifiers.
中定义 - 部分内容:
对于在该标识符的先前声明可见的范围内使用存储类说明符extern声明的标识符,23)如果先前声明指定内部或外部链接,则在后面的声明中标识符的链接是与先前声明中指定的链接相同
另见here
外部链接:具有外部链接的标识符在整个程序中表示相同的对象或功能,即在属于该程序的所有编译单元和库中。标识符可供链接器使用。当发生具有外部链接的相同标识符的第二个声明时,链接器将标识符与相同的对象或函数相关联。
答案 1 :(得分:1)
首先是这个函数定义和变量声明
int foo() {
^^^
extern i;
^^^^^^^^^
return i++;
}
无效,因为缺少参数列表和变量i
的类型说明符。
应该写成
int foo( void ) {
^^^^
extern int i;
^^^^^^^^^
return i++;
}
根据C标准(6.2.2标识符的链接)
4对于使用storage-class specifier extern声明的标识符 在该标识符的事先声明的范围内 如果事先声明指定内部或外部,则可见 联系,后来声明中标识符的链接是 与先前声明中指定的联系相同。如果没有事先 声明是可见的,或者如果先前声明指定否 链接,然后标识符有外部链接。
因此,函数中声明的变量i
没有必要具有外部链接。例如,在该演示程序中,函数内声明的变量i
具有内部链接。
#include <stdio.h>
static int i;
int foo( void )
{
extern int i;
return i++;
}
int main(void)
{
printf( "f() = %d\n", foo() );
printf( "i = %d\n", i );
return 0;
}
在应该定义为
的函数bar
中
int bar( void ) {
static int i;
return i++;
}
变量i
没有链接,但它具有静态存储持续时间。
答案 2 :(得分:0)
外部:外部变量有外部链接,extern变量的主要用法是链接其他文件中的变量,所以你说&#34; 因为它是一个局部变量,它不能在foo之外访问&#34;这是错误的,请检查以下代码。
xyz@xyz-PC:~/s_flow/alec$ vi one.c
#include<stdio.h>
int foo() {
extern i;//this is just declaration, not definition
return i++;
}
main()
{
int ret = foo();
printf("ret = %d \n",ret);
}
现在linker
会尝试在definition of "i"
或以下函数中找到other file
,如果没有找到,链接器将抛出错误。当您编译上面的代码时,您将收到链接器错误。因此,在其他文件中提供定义为
xyz@xyz-PC:~/s_flow/alec$ vi two.c
i=100;//this is definition of i
现在编译为gcc one.c two.c
&amp;检查
静态:具有internal linkage
的静态存储类意味着您无法在该文件之外使用静态变量(在其中声明它)。
xyz@xyz-PC:~/s_flow/alec$ vi one.c
main()
{
printf("i = %d \n",i);
}
现在,如果我试图访问在two.c中定义的静态变量到one.c,它将抛出错误。
xyz@xyz-PC:~/s_flow/alec$ vi two.c
void bar() {
static i = 10;
}