什么时候`extern`对于C中的变量是不可避免的?

时间:2016-01-10 15:29:13

标签: c gcc compilation extern

  

the question above的答案不回答我的问题。我知道extern 做了什么。问题是我们 需要 extern 。使用extern(并使用-fno-common进行编译)似乎只是 clean ,但似乎有时我们需要它。

类似的问题已经得到解答(例如here),但这个问题有点不同。

说,我有两个文件:

file_a.c:

#include <stdio.h>

int sixsixsix = 666;

void lucky_seven();

int main(int argc, char *argv[]){
  printf("%d\n", sixsixsix);
  lucky_seven();
  printf("%d\n", sixsixsix);
  return 0;
}

file_b.c:

int sixsixsix;

void lucky_seven(){
  sixsixsix = 777;
}

我可以使用gcc -std=c99 file_a.c file_b.c使用GCC编译而没有错误。编译后的程序按预期输出:

666
777

如果我使用-fno-common进行编译,我只会收到错误。在这种情况下,有必要在file_b.c中使用extern

file_b.c:

extern int sixsixsix;

void lucky_seven(){
  sixsixsix = 777;
}

除了这个特殊情况,也就是说,如果我有一个 的编译器将多个声明的变量放在一个公共块中,那么是否 extern用于变量的其他用途?你能给我一些extern变得不可避免的示例代码吗?

1 个答案:

答案 0 :(得分:2)

当您的项目由多个文件组成并且另一个文件中需要在其中一个源文件中定义的变量时, extern 关键字是必需的。

例如,如果在source1.c中定义变量,则必须在source2.c中将其声明为extern(直接或通过包含头文件)

引用变量的任何其他文件必须将其声明为extern。

有关使用extern关键字的非常详细说明,请参阅此post1

修改

我很好奇,因此继续搜索这个主题。

这是另一个直接解决您问题的相关post2。答案再次来自Jonathan Leaffler。

在此,为了完整起见,我将报告上述问题/答案的摘录。

帖子中提出的问题具体是:为什么如果你在两个不同的源文件中定义变量,编译器甚至不会发出警告?

简短回答是您没有违反标准中的任何约束,编译器可以自由决定要做什么。

此外,如 post1 所示,可以使用gcc和clang(以及其他编译器)编写实际可行的代码。

但为什么我们应该打扰呢? 我们知道最好使用extern!我发现在 post2 中对OP的观察非常有趣:

  

注意:这很重要,因为问题出现在上下文中   静态分析。如果两个文件可能拒绝链接某些文件   平台,分析仪应该抱怨,但如果每次编译   平台接受它然后没有理由警告它。

C标准的相关段落是:

  

J.5.11多个外部定义

     

标识符的外部定义可能不止一个   一个对象,有或没有明确使用关键字extern;如果   定义不同意,或者不止一个被初始化,   行为未定义(6.9.2)。

这意味着结果是未定义的行为(另请参阅帖子的评论)。并且,正如Jonathan Leffler所说:

  

可能发生的一件事是程序的行为和你一样   期望;和J.5.11说,大约,&#34;你可能更经常幸运   比你应得的还要多#34;

Johannes Schaub在评论中证实:

  

要明确是否允许:不,它是未定义的   在C.中的行为就像做[10] = 0;即使a是1;

的整数

结论

在多个文件中定义变量是未定义的行为,除非您正在进行某些有线测试,否则不要这样做。使用extern!