问题与“extern”在C

编程时,我想将一个大文件(包含main函数)分割成许多小文件,所以有一个常见的情况:小文件中的函数可以从main文件中修改var,所以我认为extern是非常有用的!

例如:

在main.c中

extern int i = 100; 

在small.c中

 extern int i; fprintf(stdout, "var from main file: %d\n", i); 

我只是想知道我的理解是正确的?

你将不得不改变一件事情,使其工作: extern int i = 100; 在main.c中应该改为int i = 100;

即使有可能这样做,我不认为这是一个好的设计。 你提取分离文件的东西应该是可以自己使用的,而不需要知道main.c里面的东西。

这种重构的一个有用的策略:首先移动数据,然后移动使用该数据的函数。 也就是说,首先将i变量移动到small.c ,然后移动使用i的函数。

如果你想移动函数而不是数据,请尝试传递i作为参数,而不是使用extern声明来访问它。

对的,这是可能的。 但是,不要这样做:

  // moduleA.c int c = 5; void bar(void); void foo(void) { // ... bar(); // ... } // moduleB.c extern int c; // references "c" defined in moduleA void bar(void) { // ... // do something with c // ... } 

做几乎总是好事:

  // moduleA.c int c = 5; void bar(int); void foo(void) { // ... bar(c); // ... } // moduleB.c void bar(int c) { // ... // do something with c // ... } 

换句话说,虽然你可以使用全局变量,但作为参数显式传递变量是更好的设计。 请阅读全局变量是不好的 ,以避免全局变量的各种原因。 为了突出说明为什么全局变差的原因:

  1. 他们隐藏依赖关系。 例如,当你的代码引用了全局变量“c”时,开发人员需要在整个地方搜索以找到它的定义和使用方式,因为这个变量可以被任何模块修改。 换句话说,它带来了不必要的复杂性。

  2. 全局变量由整个进程共享。 而一个被传递的局部变量将被创建在一个栈上,而每个线程都有自己的栈,全局变量共享整个程序的公共存储空间。 任何使用全局变量(除非全局变量是常量)的函数都是不可重入的,除非它锁定对全局变量的访问,否则不是线程安全的。 使用全局变量线程安全的程序是非常困难的,任何模块都可以写入全局变量的事实意味着很难确保写入变量的所有模块锁定它。

你快到了。 你只需要使用:

 int i = 100; 

main.c ,否则你会得到一个链接错误。

extern声明告诉编译器不要为该变量分配空间,但该变量将在其他地方声明。 编译器为.o文件添加一个“外部引用”,告诉链接器将引用连接到同一个变量。

如果不让编译器创建一个i变量的实际实例,就像你在问题中所做的那样,链接器将会看到所有对i的外部引用,但是不会定义 i 。 链接器将希望看到每个变量和函数的一个定义。

一个文件必须包含实际的“具体”int:

 int i = 100; 

所有其他文件应包含对int的“外部”引用:

 extern int i; 

链接器应确保它们都指向相同的内存位置。