在 GCC10 中,gcc 默认为fno-common
. 这意味着,所有暂定定义的符号都不常见。我认为 gcc 符合 C 规范,但在本机 C 程序中似乎没有通用符号。通用符号是否仅用于扩展语法?
2 回答
原生 C 有共同的符号吗?
阅读 C11 标准n1570。它的索引甚至没有提到常见的符号。
也许您指的是Linux 上用于目标文件和可执行文件的ELF文件格式。在那里,您可以找到常用符号的提及,这些符号往往已被弃用……阅读Linux ABI 规范等。
我的建议是将所有公共符号声明为extern
某个头文件(#include
大多数文件中的 -d ),并在单个翻译单元*.c
中定义一次(不使用) 。您可以使用简单的预处理器技巧(例如X-macros)。extern
您可能对使用 C 代码生成器(例如柠檬或SWIG )感兴趣,或开发您的脚本(使用GNU awk或Guile或Python或GPP等......)以获取简单的元编程技术(autoconf可能是鼓舞人心的)生成一些C 代码。适当地配置您的构建自动化工具(GNU make、ninja ...)。
您可能对使用静态分析器选项和最近 GCC 的预编译头文件感兴趣。还要查看Clang 静态分析器和clang tidy和Frama-C。
No, it has nothing to do with "extension syntax", and it has nothing to do with "common symbols" as a language construct. It simply refers to the behavior of variable declarations at file scope.
C says that if you place a declaration like int i;
in a file, and don't elaborate on it anywhere else, then it will have external linkage and it will be considered to be defined to have a value of 0. This is called a "tentative definition". Declarations with the same name in different files, if they have external linkage, all refer to the same variable. Generally the way to use external linkage is to define a variable in one file, and use an extern
declaration in any other files that make use of it.
In GCC with -fcommon
, tentative definitions for the same variable can appear in more than one file. GCC will resolve this at link time, and allocate storage (initialized to zero) for the variable once.
In GCC with -fno-common
, tentative definitions are resolved to definitions ASAP when the file is compiled. If more than one file contains a tentative definition for a variable, then this will cause a multiple definition error at link time.
As far as I can tell, the C standard doesn't require or prohibit either behavior. In particular, C does not have C++'s "one definition rule". However, the -fno-common
behavior is generally less surprising, catches a forgotten extern
sooner, and allows the compiler to optimize better (because it knows exactly where the variable lives when compiling, instead of waiting to find out later). For these reasons the default was changed in GCC.