C隐式extern用于全局变量,什么时候发生,它是如何工作的

2024-03-04

我试图了解 C 全局变量在多个文件(编译单元)之间共享的方式。我已经阅读了精彩的问答here https://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c。然而,在做了一些测试之后,我仍然有一些我没有得到的东西:

基本上我的问题是:如果在标头中声明了一个变量(但未定义),而没有extern关键字,是否可以简单地将该标头包含在各个编译单元中以使该变量可用于所有这些编译单元?在这种情况下,这意味着一个(且只有一个)编译单元包含用于初始化(定义?)该变量的代码,并且在其他编译单元尝试对该变量执行任何操作之前将首先调用它。如果这一切都是真的,那么这个过程就是所谓的“隐式外部”吗?

我将用一个例子来说明我的问题:

标头“MyCommonHeader.h”包含:

//MyCommonHeader.h
int* i; //pointer to an int

文件 MyFirstHeader.h 包含:

//MyFirstHeader.h
void changeIt(int newValue);

文件 MyFirstSource.c 包含:

//MyFirstSource.c
#include "MyFirstHeader.h"

 void changeIt(int newValue) {
    *i = newValue;
 }

文件 MySecondSource.c 包含:

//MySecondSource.c
#include "MyCommonHeader.h"
#include "MyFirstHeader.h"

void main() {
   i = malloc(sizeof(int));
   changeIt(10);
   *i = 23;
}

上面的代码是否在所有地方都使用相同的 i 变量进行操作?我需要添加吗extern任何地方?


/* file.h */
int* i;

是一个暂定的定义i多变的。这意味着如果翻译单元中该变量没有其他(外部)定义,则它将仅定义一次(初始化为0)。如果恰好有一个匹配的(外部)定义i在翻译单元的其他地方,将使用该定义,并且上面的暂定定义将充当声明。

作为一种常见的扩展,编译器跨翻译单元扩展了这种行为。这意味着,对于此类编译器,您可以安全地将该头文件包含在任意多个翻译单元中,并且仍然只有一个定义i.

如果您还显式初始化了,情况会有所不同i在头文件中:

/* file.h */
int* i = 0;

这是一个实际的定义(不是暂定的),您只能将该头文件包含在一个编译单元中,否则您会收到多重定义错误。

更好的方法是在 .c 文件中定义变量,然后使用extern在头文件中:

/* file.h */
extern int* i;

/* file.c */
int* i = 0;

这非常清楚地表明只有一个定义(.c 文件中的定义),并且包含头文件的每个编译单元都将引用该定义。

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

C隐式extern用于全局变量,什么时候发生,它是如何工作的 的相关文章

  • 将 Stream 反序列化为 List 或任何其他类型

    尝试将流反序列化为List
  • C# 创建函数队列

    我写了一个名为 QueueManager 的类 class QueueManager Queue functionsQueue public bool IsEmpty get if functionsQueue Count 0 return
  • 起订量要求?违背了目的?

    是否需要虚拟化您想要模拟的所有属性访问器就违背了模拟的目的 我的意思是 如果我必须修改我的对象并虚拟化我想要模拟的每个访问器 我难道不能继承我的类并自己模拟它吗 你的问题非常有效 但如果你仔细想想 没有其他方法可以模拟课程 如果你采用一个接
  • SharpZipLib - 将文件夹/目录添加到 zip 存档

    通过示例 我很好地掌握了如何提取 zip 文件 几乎在每个示例中 识别 ZipEntry 是否为目录的方法如下 string directoryName Path GetDirectoryName theEntry Name string
  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 如何使用 MVVM 更新 WPF 中编辑的数据? [复制]

    这个问题在这里已经有答案了 我正在为聊天应用程序构建 UI 设计 在尝试更新所选联系人的消息时遇到问题 选择现有联系人 选择编辑选项 然后编辑其属性 例如用户名和图像 后 唯一进行的更改是联系人的用户名和图像 我仍然想更改 MessageM
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 是否允许将类模板类型参数键入相同的名称?

    这似乎可以在 MSVC 中按预期编译甚至工作 但它是合法的 C 代码吗 它是否能保证执行此处所期望的操作 即将模板类型导出到结构体的同名用户 template
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • 为什么这个函数指针赋值在直接赋值时有效,但在使用条件运算符时无效?

    本示例未使用 include 在 MacOS10 14 Eclipse IDE 上编译 使用 g 选项 O0 g3 Wall c fmessage length 0 假设这个变量声明 int fun int 这无法通过 std touppe
  • 找到的程序集的清单定义与程序集引用不匹配

    我试图在 C Windows 窗体应用程序 Visual Studio 2005 中运行一些单元测试 但出现以下错误 System IO FileLoadException 无法加载文件或程序集 实用程序 版本 1 2 0 200 文化 中
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 导出类时编译器错误

    我正在使用 Visual Studio 2013 但遇到了一个奇怪的问题 当我导出一个类时 它会抛出 尝试引用已删除的函数 错误 但是 当该类未导出时 它的行为会正确 让我举个例子 class Foo note the export cla
  • 序列化和反序列化 Visual Studio 解决方案文件 - 或以编程方式编辑?

    我想以编程方式添加和删除项目 解决方案文件夹和其他项目 例如解决方案的资源文件 但我不确定最好的方法是什么 对于那些不知道的人 高度简化 解决方案文件 sln 通常如下所示 Microsoft Visual Studio Solution
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 特征密集稀疏矩阵乘积是线程化的吗?

    我知道稀疏密集产品是根据文档进行线程化的 https eigen tuxfamily org dox TopicMultiThreading html https eigen tuxfamily org dox TopicMultiThre
  • 使用 AdHocWorkspace 会导致“不支持语言‘C#’”。

    在VS2015中使用Microsoft CodeAnalysis CSharp Workspaces的RC2 这段代码会抛出异常 var tree CSharpSyntaxTree ParseText var workspace new A
  • ASP.NET Core Razor Page 多路径路由

    我正在使用 ASP NET Core 2 0 Razor Pages 不是 MVC 构建系统 但在为页面添加多个路由时遇到问题 例如 所有页面都应该能够通过 abc com language 访问segment shop mypage 或
  • C# 粘贴到文本框时检查剪贴板中的字符

    有没有一些方法可以在粘贴到文本框 C 之前仅检查剪贴板中的字符 Ctrl V 和右键单击 gt 粘贴 但不使用 MaskedTextbox 在文本框文本更改中添加规则以仅接受数字 例如 private string value privat
  • 启动画面后主窗口出现在其他窗口后面

    我有一个带有启动屏幕的 Windows 窗体应用程序 当我运行该应用程序时 启动屏幕显示正常 消失并加载应用程序的主窗体 但是 当我加载主窗体时 它出现在包含该应用程序的 Windows 资源管理器目录下 这是运行启动画面然后运行主窗体的代

随机推荐

  • Android Studio - 未找到 SDK - 设置向导失败 - 防火墙代理

    言归正传 我处于公司防火墙后面 我必须手动下载 Android Studio 的 zip 文件 并将其提取到我的计算机上的程序文件 Windows 10 中 当我启动工作室时 我的对话工作室需要检索 SDK 我尝试这样做 但在这 3 个 z
  • 如何在 iOS 上制作爆炸动画?

    我有一款 iOS 游戏 当球击中目标时就会爆炸 动画爆炸的最佳方式是什么 如果您正在寻找简单的东西 制作一系列动画爆炸的图像 将它们添加到 UIImageView 并启动动画 像这样的事情 UIImage image0 UIImage im
  • SoapUI:如何将指纹作为 SecurityTokenReference 添加到 wss SIGNATURE 条目

    我有一个关于soapUI的问题 我正在尝试将 ws security 标头添加到包含签名的肥皂请求中 为此 我在项目首选项中使用了soapUI 对话框 WS Security Configurations 它按预期工作 但我的服务器应用程序
  • 如何验证 AWS SigV4 签名

    我有一个服务器将接收带有 SigV4 授权标头的请求 并且基于 SigV4 的验证 我将授予数据访问权限 我们如何验证SigV4 我一直在尝试获取用于验证 SigV4 的文档 但无法获取它 有什么办法可以反编译签名并检查身份验证然后授权吗
  • 使用 PHP 正则表达式从字符串中删除换行符

    如何使用 PHP 从字符串中删除换行符 string str replace PHP EOL string or string str replace array n r string
  • 通过 PostMessage 发送/接收字符串

    尽管网上已经有一些资源可以解决这个粗略的主题 但我仍然没有找到适合我的答案 我希望我的同事之间能有充分的沟通VB net过程和我的C 过程 我希望能够发送一个字符串到and来自C 过程 但目前我需要实现 Sending一个字符串到C 处理并
  • MongoDB 交易

    我在 C 中有如下方法 private void Save object mongoCollection Save object someotherRelationaldb Save object 我有两个数据库 我必须在其中保存一个对象
  • 使用 VBA 访问 iframe 内的元素

    我正在尝试使用 PowerPoint VBA 访问使用 Wix Site Builder 制作的网页上的 iframe 元素 我尝试了在谷歌和其他网页上找到的所有内容 但我无法弄清楚 当我尝试使用时 最常见的错误是 自动化错误 conten
  • 如何使用TextureView代替SurfaceView与ExoPlayer的PlayerView一起使用?

    我知道可以在 ExoPlayer 中使用TextureView 但我找不到任何有关如何以正确的方式实现此功能的示例 你能帮我解决这个问题吗 The PlayerView有一个 xml 属性surface type让您选择是否要使用Surfa
  • 在 XML 中意味着什么?

    什么是
  • 如何在 Eclipse 模拟器中创建代表 Samsung Galaxy S 的 AVD?

    我正在开发一款专门针对三星 Galaxy S 的应用程序 我不是在这里做出决定的人 他们希望其布局达到像素精度 我可以只使用普通的 2 1 AVD 吗 所以我尝试创建 WQVGA432 但它看起来像这样 我不知道为什么 LinearLayo
  • 构建参数未解决

    我有 docker compose 和以下代码 version 3 8 services php container name php build context php args PHPVERSION 7 4 XDEBUGVERSION
  • 如何触发/强制更新 Svelte 组件

    我正在尝试了解 svelte 3 反应性的事情 我想在单击按钮时强制刷新用户界面 我正在使用自定义组件AsyncFetcher接受 HTTP post 数据并返回data其插槽的对象 http post 结果 我想要一个禁用功能 因此 当单
  • HttpWebRequest 和本机 GZip 压缩

    当请求使用 Gzip 压缩的页面时 我收到很多以下错误 System IO InvalidDataException GZip 页脚中的 CRC 与 根据解压后计算出的CRC 数据 我正在使用本机 GZipStream 来解压缩 并正在考虑
  • 在虚拟 getter 中添加参数

    我想做的是这样的 Schema virtual getSomething get function what if what return this somethingElse else return this something what
  • Laravel 5 - 写入供应商目录

    Laravel 5 在工作一段时间后崩溃了 这是错误 file put contents Library WebServer Documents project vendor services json 无法打开流 权限被拒绝 在 File
  • java.lang.UnsatisfiedLinkError:dlopen失败:找不到库“/Users/...”

    我想添加另一个库android ndk hello libs https github com googlesamples android ndk issues 364例子 In CMakeLists txt I add this is f
  • MediaRecorder:启动失败

    我已经用谷歌搜索过但没有找到任何解决方案 我正在记录来电和去电 code 与拨出电话配合使用效果良好但给出来电异常 recorder new MediaRecorder File sdCard Environment getExternal
  • 使用 proc_open() 加载 .profile

    情况是这样的 我编写了一个后端应用程序 在某个服务器上运行 在此服务器上 有一个可以通过 ssh 从前端服务器执行的脚本 然后 我的脚本将检查它所需的环境变量是否已正确加载 因为我在脚本本身中严重依赖它们 这可行 尽管不是我想要的方式 建立
  • C隐式extern用于全局变量,什么时候发生,它是如何工作的

    我试图了解 C 全局变量在多个文件 编译单元 之间共享的方式 我已经阅读了精彩的问答here https stackoverflow com questions 1433204 what are extern variables in c