链接本地`extern`变量

时间:2017-11-13 18:30:50

标签: c static c99 extern

我估计以前可能已经回答了这个问题。如果有,请标记为副本!

我无法理解extern对局部变量(或局部函数!)的意义。我似乎无法看到它在功能上与static局部变量有何不同......例如:

int foo(void) {
   extern int i;
   return i++;
}

int bar(void) {
   static int i;
   return i++;
}

AFAICT,foobar是相同的。根据C99规范的差异是i中的fooi中的bar相比应该具有外部链接。也就是说,我想不出任何方式来利用外部链接 - 因为它是一个局部变量,它不能在foo之外访问,更不用说在文件之外了。

我确定我在这里遗漏了什么 - 它是什么?

修改

感谢所有指出我在externstatic上遗漏了类型的人。你是对的。作为SO的常见回答者,我现在明白了在这种疏忽之后投票的挫败感令人沮丧。

3 个答案:

答案 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;
}