怀疑与extern关键字使用有关

时间:2010-02-27 19:46:59

标签: c extern

AFAIK,extern关键字应该用于声明,并且没有值可以与使用extern关键字声明的变量相关联。但假设我写了一个像

这样的陈述
extern int i = 10;

编译器是否应标记错误?我看到一些编译器容忍并忽略了这一点?为什么会这样? 'C'标准对此有何看法?

编辑:@All,谢谢你的回答。我仍有疑问。假设我有这个变量的定义而没有另一个文件中的extern链接说a.c而我在b.c中添加了这个语句。仍然可以让编译器不标记错误吗?它是否会被重新定义?

4 个答案:

答案 0 :(得分:5)

这是有效的语法,在C99标准中甚至有一个基本相同的例子。 (见§6.9.2-4。)

这些例子确实不是规范性的,但我相信它的目的是成为合法的语法。编译器通常会输出一个警告,因为它并没有真正完成任何事情。

4示例1

int i1 = 1;             // definition, external linkage
static int i2 = 2;      // definition, internal linkage
extern int i3 = 3;      // definition, external linkage
int i4;                 // tentative definition, external linkage
static int i5;          // tentative definition, internal linkage
int i1;                 // valid tentative definition, refers to previous
int i2;                 // 6.2.2 renders undefined, linkage disagreement
int i3;                 // valid tentative definition, refers to previous
int i4;                 // valid tentative definition, refers to previous
int i5;                 // 6.2.2 renders undefined, linkage disagreement
extern int i1;          // refers to previous, whose linkage is external
extern int i2;          // refers to previous, whose linkage is internal
extern int i3;          // refers to previous, whose linkage is external
extern int i4;          // refers to previous, whose linkage is external
extern int i5;          // refers to previous, whose linkage is internal

答案 1 :(得分:4)

以下代码;

extern int i ;

声明变量i,但不实例化它。如果它也没有在同一个编译单元中定义,链接器将尝试从包含最终可执行文件的目标文件和库中解析它。

然而你的例子是:

extern int i = 10 ;

初始化对象,因此也必须实例化它。在这种情况下,extern关键字是多余的,因为对象在同一个编译单元中初始化(实际上是相同的语句)。它相当于:

extern int i ;  // redundant
int i = 10 ;

虽然在最后一个示例中,extern关键字是多余的,但它完全等同于在头文件中声明的全局变量时所具有的内容,并且实例化一个源文件,也包含该头文件(因为它应该允许编译器执行类型检查)。

您可以按如下方式测试:

extern int i ;
int main()
{
    i = 10 ;
}

以上将导致未解析变量i的链接器错误。鉴于:

extern int i = 10 ;
int main()
{
    i = 10 ;
}

会毫无问题地链接。

答案 2 :(得分:0)

extern关键字表示给定变量在不同的模块中分配。它与访问与该变量无关。分配给外部变量是完全合法的。

答案 3 :(得分:-1)

extern关键字的目的是为实体提供外部链接。无论是在声明中使用还是在定义中使用都没有区别。您发布的代码绝对没有错误。

如果您更愿意在“导出与导入”方面考虑,那么extern关键字应用于非定义声明意味着我们导入< / em>在其他一些翻译单元中定义的实体。当extern关键字应用于定义时,表示我们导出此实体以供其他翻译单元使用。 (虽然值得注意的是“出口与进口”并不完全是思考C联动概念的标准方式。)

您不会经常看到定义中使用的关键字的原因是因为在C文件范围定义中默认具有外部链接。所以写作

extern int i = 10;

是有效的,但是多余的,因为它等同于普通的

int i = 10;

然而,在实际代码中,您可能会不时看到人们将此关键字与函数声明和定义一起使用,即使它在那里也是多余的

extern void foo(int i); /* `extern` is superfluous */
...
extern void foo(int i) /* `extern` is superfluous */
{
  /* whatever */
}