编程时,我想将一个大文件(包含main函数)拆分成许多小文件,所以有一个常见的情况:小文件中的函数可以修改主文件中的var,所以我认为extern非常有用!
例如:
在main.c中
extern int i = 100;
in small.c
extern int i;
fprintf(stdout, "var from main file: %d\n", i);
我只是想知道我的理解是对吗?
答案 0 :(得分:6)
您必须更改一件事才能使其正常工作:main.c中的extern int i = 100;
应更改为int i = 100;
即使可以这样做,我也不认为这是一个好的设计。您提取的用于分隔文件的内容应该可以单独使用,而不必了解main.c
内的内容。
这种重构的有用策略:首先移动数据,然后移动使用该数据的函数。也就是说,首先将i
变量移至small.c
,然后移动使用i
的函数。
如果您想移动函数而不是数据,请尝试将i
作为参数传递,而不是使用extern
声明来访问它。
答案 1 :(得分:2)
是的,有可能。但是,而不是:
// 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
// ...
}
换句话说,虽然您可以使用全局变量,但明确地将变量作为参数传递是更好的设计。请阅读Global Variables are Bad,原因有多种,以避免全局变量。为了突出全局变坏的几个原因:
他们隐藏了依赖关系。例如,当您的代码引用全局变量“c”时,开发人员需要遍布整个地点以查找它的定义位置以及如何使用它,因为任何模块都可以修改此变量。换句话说,它引入了不必要的复杂性。
全局变量由整个过程共享。虽然传递的局部变量将在堆栈上创建,并且每个线程都有自己的堆栈,但globals共享整个程序的公共存储。使用全局变量的任何函数(除非该全局变量是常量)是不可重入的,除非它锁定对该全局变量的访问,否则它不是线程安全的。使用全局变量线程安全的程序是非常困难的,并且任何模块都可以写入全局变量的事实意味着很难确保写入变量的所有模块都锁定它。
< / LI> 醇>答案 2 :(得分:1)
你快到了。你需要使用:
int i = 100;
在main.c
中,否则会出现链接器错误。
extern
声明告诉编译器不要为该变量分配空间,但该变量将在其他地方声明。编译器向.o
文件添加一个“外部引用”,告诉链接器将引用连接到同一个变量。
在不让编译器创建i
变量的实际实例的情况下,正如您在问题中所做的那样,链接器将看到i
的所有外部引用但不是i
的定义。链接器希望只查看每个变量和函数的一个定义。
答案 3 :(得分:1)
一个文件必须包含实际的“具体”int:
int i = 100;
所有其他文件应包含对int的“外部”引用:
extern int i;
然后,链接器应确保它们都指向相同的内存位置。