原生 C 有公共符号吗?
Does native C have common symbol?
在 GCC10 中,gcc 默认为 fno-common
。也就是说,所有暂定的符号都不通用。我认为 gcc 符合 C 规范,但在本机 C 程序中似乎没有公共符号。常用符号只用于扩展语法吗?
Does native C have common symbol?
阅读 C11 标准 n1570。 它的索引甚至没有提到常用符号。
另请仔细阅读 documentation of GCC and this draft 报告。
也许你指的是ELF file format used on Linux for object files and executables. There you can find a mention of common symbols, which tend to be deprecated .... Read the Linux ABI specification, etc here。
我的建议是在某些头文件中将所有 public 符号声明为 extern
(在大多数 *.c
文件中为 #include
-d),并定义他们一次(没有extern
)在单个 translation unit. You could use simple preprocessor tricks (such as X-macros).
您可能有兴趣适当地使用 C 代码生成器,例如 lemon or SWIG, or develop your script (with GNU awk or Guile or Python or GPP etc... ....) for simple metaprogramming techniques (autoconf could be inspirational) generating some C code. Configure your build automation tool (GNU make, ninja...)。
您可能有兴趣使用 static analyzer options and precompiled headers of recent GCC. Look also into Clang static analyzer and clang tidy and Frama-C。
你肯定想通过-Wall -Wextra -g -H
to gcc
and read How to debug small programs and Modern C.
不,它与 "extension syntax" 无关,也与作为语言结构的 "common symbols" 无关。它只是指变量声明在文件范围内的行为。
C 说如果你在文件中放置像 int i;
这样的声明,并且不在其他任何地方详细说明它,那么它将具有外部 linkage 并且将被视为被定义为具有值 0。这称为 "tentative definition"。不同文件中的同名声明,如果有external linkage,都指向同一个变量。通常使用外部 linkage 的方法是在一个文件中定义一个变量,并在任何其他使用它的文件中使用 extern
声明。
在具有 -fcommon
的 GCC 中,同一变量的暂定定义可以出现在多个文件中。 GCC 将在 link 时间解决这个问题,并为变量分配一次存储空间(初始化为零)。
在带有 -fno-common
的 GCC 中,暂定定义会在编译文件时尽快解析为定义。如果多个文件包含一个变量的暂定定义,那么这将在 link 次导致多重定义错误。
据我所知,C 标准不要求或禁止 任一 行为。特别是C没有C++的"one definition rule"。然而,-fno-common
行为通常不那么令人惊讶,更快地捕获被遗忘的 extern
,并允许编译器更好地优化(因为它在编译时确切地知道变量所在的位置,而不是等到以后才发现).由于这些原因,GCC 中的默认值已更改。
在 GCC10 中,gcc 默认为 fno-common
。也就是说,所有暂定的符号都不通用。我认为 gcc 符合 C 规范,但在本机 C 程序中似乎没有公共符号。常用符号只用于扩展语法吗?
Does native C have common symbol?
阅读 C11 标准 n1570。 它的索引甚至没有提到常用符号。
另请仔细阅读 documentation of GCC and this draft 报告。
也许你指的是ELF file format used on Linux for object files and executables. There you can find a mention of common symbols, which tend to be deprecated .... Read the Linux ABI specification, etc here。
我的建议是在某些头文件中将所有 public 符号声明为 extern
(在大多数 *.c
文件中为 #include
-d),并定义他们一次(没有extern
)在单个 translation unit. You could use simple preprocessor tricks (such as X-macros).
您可能有兴趣适当地使用 C 代码生成器,例如 lemon or SWIG, or develop your script (with GNU awk or Guile or Python or GPP etc... ....) for simple metaprogramming techniques (autoconf could be inspirational) generating some C code. Configure your build automation tool (GNU make, ninja...)。
您可能有兴趣使用 static analyzer options and precompiled headers of recent GCC. Look also into Clang static analyzer and clang tidy and Frama-C。
你肯定想通过-Wall -Wextra -g -H
to gcc
and read How to debug small programs and Modern C.
不,它与 "extension syntax" 无关,也与作为语言结构的 "common symbols" 无关。它只是指变量声明在文件范围内的行为。
C 说如果你在文件中放置像 int i;
这样的声明,并且不在其他任何地方详细说明它,那么它将具有外部 linkage 并且将被视为被定义为具有值 0。这称为 "tentative definition"。不同文件中的同名声明,如果有external linkage,都指向同一个变量。通常使用外部 linkage 的方法是在一个文件中定义一个变量,并在任何其他使用它的文件中使用 extern
声明。
在具有 -fcommon
的 GCC 中,同一变量的暂定定义可以出现在多个文件中。 GCC 将在 link 时间解决这个问题,并为变量分配一次存储空间(初始化为零)。
在带有 -fno-common
的 GCC 中,暂定定义会在编译文件时尽快解析为定义。如果多个文件包含一个变量的暂定定义,那么这将在 link 次导致多重定义错误。
据我所知,C 标准不要求或禁止 任一 行为。特别是C没有C++的"one definition rule"。然而,-fno-common
行为通常不那么令人惊讶,更快地捕获被遗忘的 extern
,并允许编译器更好地优化(因为它在编译时确切地知道变量所在的位置,而不是等到以后才发现).由于这些原因,GCC 中的默认值已更改。