原生 C 有共同的符号吗?
Posted
技术标签:
【中文标题】原生 C 有共同的符号吗?【英文标题】:Does native C have common symbol? 【发布时间】:2020-09-24 06:35:44 【问题描述】:在 GCC10 中,gcc 默认为fno-common
。这意味着,所有暂定定义的符号都不常见。我认为 gcc 符合 C 规范,但在本机 C 程序中似乎没有通用符号。通用符号是否仅适用于扩展语法?
【问题讨论】:
“通用”符号在旧语言(主要是 Fortran)中似乎很常见(不是双关语)。 GCC 是 GNU Compiler Collection 的缩写,它是许多不同语言的编译器的集合。由于 Fortran 是受支持的语言之一,GCC 仍然必须支持通用符号。 @Someprogrammerdude 不相关。-fno-common
/ -fcommon
是特定于 C 的标志。
【参考方案1】:
原生C有通用符号吗?
阅读 C11 标准 n1570。 它的索引甚至没有提到常见的符号。
还请仔细阅读documentation of GCC 和this draft 报告。
也许你参考了在 Linux 上使用的ELF 文件格式object files 和executables。在那里你可以找到常用符号的提及,这些符号往往被弃用....阅读 Linux ABI 规范等here。
我的建议是在某些头文件中将所有公共符号声明为extern
(在大多数*.c
文件中为#include
-d),并定义它们一次(不带@ 987654353@) 在单个 translation unit。您可以使用简单的preprocessor 技巧(例如X-macros)。
您可能有兴趣使用 C 代码生成器,例如 lemon 或 SWIG,或开发您的脚本(使用 GNU awk 或 Guile 或 Python 或 GPP 等...... .) 对于简单的metaprogramming 技术(autoconf 可能是鼓舞人心的)生成一些 C 代码。适当配置您的build automation 工具(GNU make、ninja...)。
您可能有兴趣使用最近的 GCC 的 static analyzer options 和 precompiled headers。还要查看Clang static analyzer 和clang tidy 和Frama-C。
您肯定想通过-Wall -Wextra -g -H
to gcc
并阅读How to debug small programs 和Modern C。
【讨论】:
【参考方案2】:不,它与“扩展语法”无关,与作为语言结构的“通用符号”无关。它只是指文件范围内变量声明的行为。
C 表示,如果您将 int i;
之类的声明放在文件中,并且在其他任何地方都没有详细说明,那么它将具有外部链接,并且将被认为定义为值为 0。这被称为“暂定定义”。不同文件中同名的声明,如果有外部链接,都指向同一个变量。通常使用外部链接的方法是在一个文件中定义一个变量,并在使用它的任何其他文件中使用extern
声明。
在带有-fcommon
的GCC 中,同一变量的暂定定义可以出现在多个文件中。 GCC 将在链接时解决此问题,并为变量分配一次存储空间(初始化为零)。
在带有-fno-common
的 GCC 中,暂定定义在文件编译时尽快解析为定义。如果多个文件包含一个变量的暂定定义,那么这将导致链接时出现多重定义错误。
据我所知,C 标准不要求或禁止任何一种 行为。特别是,C 没有 C++ 的“单一定义规则”。但是,-fno-common
的行为通常不那么令人惊讶,它会更快地捕获被遗忘的extern
,并允许编译器更好地优化(因为它在编译时确切地知道变量所在的位置,而不是等待稍后发现)。由于这些原因,GCC 中的默认值已更改。
【讨论】:
Re“据我所知,C 标准不要求或禁止任何一种行为”:C 2018 6.9 5 涵盖了这一点,“……如果使用通过外部链接声明的标识符在一个表达式中……,在整个程序的某个地方,应该有一个标识符的外部定义;否则,不得超过一个。”由于它出现在约束部分之外,因此违反它不需要诊断,但会使行为被 C 标准“未定义”,该标准授权 C 实现以支持常见或非常见行为。以上是关于原生 C 有共同的符号吗?的主要内容,如果未能解决你的问题,请参考以下文章