0

我对 extern 的以下行为感到惊讶。

当我运行这个

#include<stdio.h>
int main()
{
    extern int a;
    printf("%d\n", a);
    return 0;
}
int a=20;

输出: 20(在 gcc Linux 32 位中,看起来还可以)

a但是当我在里面声明变量时main()

#include<stdio.h>
int main()
{
    extern int a;
    int a=20;
    printf("%d\n", a);
    return 0;
}

输出:

extern.c: In function ‘main’:
extern.c:5:9: error: declaration of ‘a’ with no linkage follows extern declaration
extern.c:4:16: note: previous declaration of ‘a’ was here

为什么在将范围a从全局更改为本地后现在出现错误?为什么它现在不允许重新声明a,而在以前的情况下允许。

4

2 回答 2

7

声明的重点extern是告诉编译器一个全局变量或函数被多个编译单元(.c文件)使用,但在单个编译单元中定义和分配。声明放置在所有单元包含的extern头文件中,单个编译单元包含实际定义,因此可以看到两者。

您的第一个示例是合法的 C:您声明它将a引用外部定义的变量,然后继续在当前编译单元中定义该变量。通常,该extern声明将包含在头文件中,因此在编译器中显示在顶层,而不是在函数内部,但编译器并不关心任何一种方式。换句话说,这里没有重新定义,只有声明后的定义。

您的第二个示例声明a具有外部链接,然后继续将其定义为main. 声明和定义显然是不兼容的——如果a是局部变量,则不能只在一个地方定义和分配——而是在每次调用函数时自动在堆栈上分配。这种不兼容会导致错误诊断。

于 2013-09-15T07:03:18.637 回答
3

在第一个示例中,您告诉编译器:“嘿,我有一个a在其他地方定义的名为的变量。”,然后您使用它。没关系。

#include<stdio.h>
int main()
{
    extern int a;
    printf("%d\n", a);
    return 0;
}
int a=20;

在第二个示例中,您还告诉编译器在程序中的某个地方有一个a您想要使用的变量,然后您在堆栈上声明了一个具有相同名称的新变量。这没有多大意义,编译器说了两件事:在程序中找不到任何变量声明,a并且变量a已经存在(如果你修复了第一个错误,它会)。

#include<stdio.h>
int main()
{
    extern int a;
    int a=20;
    printf("%d\n", a);
    return 0;
}

当你声明一个全局变量时,它的内存是在程序启动时分配的(它在二进制文件中并映射到内存中)。当您声明一个局部变量时,内存在函数执行期间分配在堆栈上。您不能使用 extern 引用尚不存在的变量。

于 2013-09-15T07:14:57.157 回答