当两个 .c 文件具有相同符号但不同类型的全局变量时,引用如何工作?

2024-02-09

C

假设我有以下 C 模块:

MODULE 1

#include <stdio.h>
int x;
int main(){
  foo();
  printf("%i\n",x);
  return 0;
}

MODULE 2

double x;
void foo(){
  x = 3.14;
}

我的问题是:在这种情况下链接器会做什么?在我读的教科书中,它说编译器只为链接器符号表选择两个弱全局变量之一。这两个选择哪个?还是两者都选择了?如果是这样,为什么?谢谢。


C 说这是未定义的行为。

(C99, 6.9p5) “如果在表达式中使用使用外部链接声明的标识符(而不是作为结果为整型常量的 sizeof 运算符的操作数的一部分),则在整个程序中的某处应该恰好有一个外部链接标识符的定义;否则,不得超过一个”

未定义的行为意味着链接器可以在存在多个外部对象定义的情况下中止链接过程。

现在链接器很好(或者evil,您可以选择)并且通常具有默认扩展来处理多个外部对象定义并且在某些情况下不会失败。

如果您正在使用gcc and ld从 binutils 中,如果您的两个对象被显式初始化,您将收到错误。例如,你有int x = 0;在第一个翻译单元中和double x = 0.0;.

否则,如果外部对象之一未显式初始化(​​您示例中的情况)gcc会默默地将两个对象组合成一个符号。您仍然可以通过向链接器传递选项来要求链接器报告警告--warn-common.

例如链接模块时:

gcc -Wl,--warn-common module1.o module2.o

要中止链接过程,您可以使用以下命令请求链接器将所有警告视为错误--fatal-warnings选项 (-Wl,--fatal-warnings,--warn-common).

中止链接过程的另一种方法是使用-fno-common编译器选项,如所解释的@teppic https://stackoverflow.com/users/1627348/teppic在他的回答中。-fno-common禁止外部对象在编译时获取通用符号类型。如果您对两个模块都执行此操作然后链接,您还会收到多重定义链接器错误。

gcc -Wall -fno-common -c module1.c module2.c

gcc module1.o module2.o

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当两个 .c 文件具有相同符号但不同类型的全局变量时,引用如何工作? 的相关文章

  • 无法将匿名方法转换为类型“System.Windows.Threading.DispatcherPriority”,因为它不是委托类型

    谁能解释我需要做什么才能克服这个错误 无法将匿名方法转换为类型 System Windows Threading DispatcherPriority 因为它不是委托类型 private void Test object sender ba
  • 在c中用以下结构填充矩阵

    我有以下结构 typedef struct arr integer int size int arr arr arr integer arr arr integer alloc arr integer int len arr arr int
  • 哪些 iomanip 操纵器具有“粘性”?

    我最近在创建一个stringstream由于我错误地假设std setw 会影响每次插入的字符串流 直到我明确更改它 然而 插入后它总是被取消设置 With timestruct with value of Oct 7 9 04 AM st
  • .Net Core 中 String 默认不可序列化吗?

    我正在查看其他的 Fortify 静态分析安全测试 SAST 扫描报告 以识别和抑制误报 应用程序框架是C NET Core SAST 报告部分内容如下 Method1 在第 111 行将不可序列化的对象存储为 HttpSessionSta
  • 请求的资源不支持 HTTP 方法“GET”

    我的路线配置正确 并且我的方法具有装饰标签 我仍然收到 请求的资源不支持 HTTP 方法 GET 消息 System Web Mvc AcceptVerbs GET POST System Web Mvc HttpGet public st
  • 在 C# 中实例化 python 类

    我已经用 python 编写了一个类 我想通过 IronPython 将其包装到 net 程序集中 并在 C 应用程序中实例化 我已将该类迁移到 IronPython 创建了一个库程序集并引用了它 现在 我如何真正获得该类的实例 该类看起来
  • System.MissingMethodException:找不到方法?

    以前工作的 ASP NET WebForms 应用程序现在抛出此错误 System MissingMethodException 找不到方法 The DoThis方法位于同一个类上 它应该可以工作 我有一个这样的通用处理程序 public
  • 如何在函数中将结构成员作为指针传递?

    问题是我有一个结构是另一个 主要 结构的成员 我编写了一个函数来清除第一个结构 它需要一个指向结构的指针 我想使用该函数来清除主要结构内的结构 但我不确切知道哪种方法是正确的 为了更好地解释它 这里有一些代码 我有一个结构 定义为 type
  • 使用inotify监控文件

    我正在使用 inotify 来监视本地文件 例如使用 root temp inotify add watch fd root temp mask 删除该文件后 程序将被阻止read fd buf bufSize 功能 即使我创建一个新的 r
  • ASP .NET MVC 5 - 客户地址一对一关系

    我在这里查看了论坛 实际上发现了一些类似的问题 但不是相同的问题 类似的解决方案没有给我正确的答案 我正在使用实体框架和代码优先方法来处理 ASP NET MVC 5 我想建立客户 gt 地址一对一关系的模型 我建模的是 客户等级 publ
  • 实体框架 5 不清除导航属性

    我在 Entity Framework 5 中遇到了这个奇怪的问题 我在其中一个实体中有一个导航属性 我想将其设置为null 但由于某种原因 该属性只有在我第二次调用该属性时才会被清除 using var db new Entities v
  • 混合 VS2012 平台工具集

    我们正在从 VS2005 切换到 VS2012 update 2 我们正在构建大量 主要是控制台 本机 C 无 MFC ATL 可执行文件 它们使用几个常见的静态链接库 这些可执行文件主要在 Win7 计算机上运行 但有些也部署在较旧的 X
  • 我需要一个树转储选项,该选项在当前的 gcc 版本中不再存在

    旧版本的 GCC 例如 4 0 2 或 4 1 2 有该选项 df see 用于调试程序或 GCC 的选项对于4 1 2 http gcc gnu org onlinedocs gcc 4 1 2 gcc Debugging Options
  • 接口中的私有成员

    是否可以在 NET 接口中创建私有成员 我听说现在可以了 但我的 IDE 拒绝了 public interface IAnimal void SetDefaultName string name ChangeName name privat
  • tcmalloc/jemalloc 和内存池之间有什么区别(以及选择的理由)?

    tcmalloc jemalloc是改进的内存分配器 还引入了内存池以更好地分配内存 那么它们之间有什么区别以及在我的应用中如何选择它们呢 这取决于您的程序的要求 如果您的程序有更多的动态内存分配 那么您 需要从可用的分配器中选择一个内存分
  • 那里有更好的 DateTime.Parse 吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个库 付费或免费 能够处理比 DateTime Parse 使用的更常见的日期时间格式 能够
  • 为什么 C# 编译的正则表达式比等效的字符串方法更快?

    每次我必须对字符串执行简单的包含或替换操作 其中我正在搜索的术语是固定值 时 我发现如果我获取示例输入并对其进行一些分析 则使用编译的正则表达式是几乎 总是比使用 String 类中的等效方法更快 我尝试过比较多种方法 hs是要搜索的 干草
  • 为 C++ 类播种 rand()

    我正在开发一个 C 类 它使用rand 在构造函数中 我真的希望这个班级在几乎所有方面都能照顾好自己 但我不知道在哪里播种rand 如果我播种rand 在构造函数中 每次构造我的对象类型的新实例时都会对其进行播种 因此 如果我按顺序创建 3
  • 为什么没有参数的函数(与实际函数定义相比)可以编译?

    我刚刚看到某人的 C 代码 我很困惑为什么要编译它 有两点我不明白 The 函数原型与实际函数定义相比没有参数 中的参数函数定义没有类型 include
  • MsBuild 在 Visual Studio Online 上找不到恢复的 NuGet 包

    我尝试构建一个存储在 Visual Studio Online 上的外部 GIT 存储库中的解决方案 它有以下步骤 1 Git 恢复 有效 2 NuGet 恢复 有效 3 构建 不起作用 查看日志时我的第一个猜测是 MsBuild 没有查找

随机推荐