原生 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 programsModern 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 有共同的符号吗?的主要内容,如果未能解决你的问题,请参考以下文章

bool 是原生 C 类型吗?

云原生距离我们有多远

将libavdevice.a链接到libffmpeg.so时找不到NDK摄像头和媒体原生API符号

招行架构师徐佳航:金融云原生与开源标准的共同生长

引领云原生2.0,华为云加速云原生全行业落地

云原生之服务网格介绍与Istio入门