什么时候对于 C 中的变量来说 `extern` 是不可避免的?
When is `extern` unavoidable for variables in C?
Answers to the question above don't answer my question. I know what extern
does. The question is if we ever need extern
. It only seems cleaner to use extern
(and compile with -fno-common
), but it doesn't seem there are situations when we need it.
类似的问题已经有人回答了(例如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
变得不可避免吗?
当您的项目包含多个文件并且另一个源文件中需要一个源文件中定义的变量时,extern 关键字是必需的。
例如,如果你定义source1.c中的变量,那么你必须在[=]中将其声明为extern 81=](直接或通过包含头文件)。
引用变量 的任何其他文件必须 将其声明为外部。
请参阅此post1 非常非常 extern 关键字用法的详细说明
编辑
我很好奇,于是继续搜索这个话题。
这是另一个相关的 post2,它直接解决了您的问题。答案再次来自 Jonathan Leaffler。
在此,为了完整起见,我将报告上述内容的摘录question/answer。
post 中提出的问题具体如下:为什么如果您在两个不同的源文件中定义一个变量,编译器甚至不会发出警告?
简短的回答是您没有违反标准中的任何约束,编译器可以自由决定要做什么。
此外,如 post1 所示,可以使用 gcc 和 clang(也可能还有其他编译器)编写实际有效的代码。
但我们为什么要费心呢? 我们知道最好使用 extern! 我发现对 OP 的观察非常有趣post2:
Note: this is important because the question occurs in the context of
static analysis. If the two files may refuse to be linked on some
platform, the analyzer should complain, but if every compilation
platform accepts it then there is no reason to warn about it.
C标准的相关段落为:
J.5.11 Multiple external definitions
There may be more than one external definition for the identifier of
an object, with or without the explicit use of the keyword extern; if
the definitions disagree, or more than one is initialized, the
behavior is undefined (6.9.2).
这意味着结果是未定义的行为(另请参阅 post 的注释)。而且,正如 Jonathan Leffler 所说:
One of the things that can happen is that the program behaves as you
expect; and J.5.11 says, approximately, "you might be lucky more often
than you deserve"
Johannes Schaub 在评论中确认:
To be really clear whether it's allowed or not: No it's undefined
behavior in C. It's like doing a[10] = 0; even if a is a int a1;
结论
在多个文件中定义一个变量是未定义的行为,除非你正在做一些有线测试,否则不要这样做。使用外部!
Answers to the question above don't answer my question. I know what
extern
does. The question is if we ever needextern
. It only seems cleaner to useextern
(and compile with-fno-common
), but it doesn't seem there are situations when we need it.
类似的问题已经有人回答了(例如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
变得不可避免吗?
当您的项目包含多个文件并且另一个源文件中需要一个源文件中定义的变量时,extern 关键字是必需的。
例如,如果你定义source1.c中的变量,那么你必须在[=]中将其声明为extern 81=](直接或通过包含头文件)。
引用变量 的任何其他文件必须 将其声明为外部。
请参阅此post1 非常非常 extern 关键字用法的详细说明
编辑
我很好奇,于是继续搜索这个话题。
这是另一个相关的 post2,它直接解决了您的问题。答案再次来自 Jonathan Leaffler。
在此,为了完整起见,我将报告上述内容的摘录question/answer。
post 中提出的问题具体如下:为什么如果您在两个不同的源文件中定义一个变量,编译器甚至不会发出警告?
简短的回答是您没有违反标准中的任何约束,编译器可以自由决定要做什么。
此外,如 post1 所示,可以使用 gcc 和 clang(也可能还有其他编译器)编写实际有效的代码。
但我们为什么要费心呢? 我们知道最好使用 extern! 我发现对 OP 的观察非常有趣post2:
Note: this is important because the question occurs in the context of static analysis. If the two files may refuse to be linked on some platform, the analyzer should complain, but if every compilation platform accepts it then there is no reason to warn about it.
C标准的相关段落为:
J.5.11 Multiple external definitions
There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
这意味着结果是未定义的行为(另请参阅 post 的注释)。而且,正如 Jonathan Leffler 所说:
One of the things that can happen is that the program behaves as you expect; and J.5.11 says, approximately, "you might be lucky more often than you deserve"
Johannes Schaub 在评论中确认:
To be really clear whether it's allowed or not: No it's undefined behavior in C. It's like doing a[10] = 0; even if a is a int a1;
结论
在多个文件中定义一个变量是未定义的行为,除非你正在做一些有线测试,否则不要这样做。使用外部!