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用于全局变量,什么时候发生,它是如何工作的 的相关文章

  • 分层架构中的异常处理

    我们正在分层设计中重构 当然还有重新设计 我们的服务 我们有服务操作层 BLL 网络抽象层 gt 处理网络代理 数据抽象层 但我们对我们的异常处理策略有点困惑 我们不想向外界透露太多 BLL 的信息 从其他层到bll就可以了 我们不想让 t
  • C++ 返回值、引用、const 引用

    你能向我解释一下返回值 值引用和值常量引用之间的区别吗 Value Vector2D operator const Vector2D vector this gt x vector x this gt y vector y return t
  • 使用预编译头减少 clang 编译时间

    我正在开发一个数据库项目 该项目将查询 以某种高级语言表示 编译为 C 代码 这段代码由数据库编译并执行 那部分工作得很好 现在 我正在尝试减少 C 查询代码的编译时间 我想知道是否可以使用预编译头来提高性能 该查询被转换为一个名为 Que
  • 代码块 power 函数在 c 中不起作用

    我正在使用代码块来学习c 我的代码是 include
  • 操作/Lambda 表达式内存管理问题

    我将一个操作存储在局部变量中 然后在该局部变量超出范围后使用 使用前是否有被清理的危险 这是一个例子 public List GetMaps Action
  • C++:将模板参数的模板类型成员添加为好友的正确语法?

    我有一个带有模板类型参数 tTRAIT 的类 我想加一个模板为好友type member aliastTRAIT 但我无法弄清楚语法 这可能吗 template
  • StreamReader,C#,peek

    我有一个 StreamReader 它偶尔会检查它是否有更多内容可以从简单的文本文件中读取 它使用 peek 属性 问题是 当我使用 peek 时 位置发生了变化 尽管不应该发生 FileStream m fsReader new File
  • 求一个数的因数。无法得到准确的结果

    有人可以帮助纠正我的算法吗 我已经对几个数字进行了测试 但它没有输出完整的因式分解 对于具有大量因子的数字 它完全失败 int num 20 for int i 2 i lt num i if num i 0 cout lt lt i lt
  • Qt QML 数据模型似乎不适用于 C++

    我一直在使用中的示例http doc qt digia com 4 7 qdeclarativemodels html http doc qt digia com 4 7 qdeclarativemodels html这是 QML 声明性数
  • 命名空间“Microsoft”中不存在类型或命名空间名称“Practices”

    我正在使用 Microsoft Visual Studio 2005 for c 我的代码中有以下命名空间 using Microsoft Practices EnterpriseLibrary using Microsoft Practi
  • printf() 使用字符串表“解码器环”调试库

    我写这封信是想看看你们中是否有人见过或听说过我即将描述的想法的实现 我有兴趣为嵌入式目标开发 printf 风格的调试库 目标非常遥远 并且我和目标之间的通信带宽预算非常紧张 因此我希望能够以非常有效的格式获取调试消息 通常 调试语句如下所
  • 该组件没有由 uri 标识的资源

    我想创建一个通用数据网格以在我的所有视图 用户控件上使用 这是我的结构 Class Library called Core Class called ViewBase public class ViewBase UserControl pu
  • EWS - 给予预约,获取预约的所有者副本

    在 EWS 中进行预约后 是否可以获得所有者的副本 例如 如果我登录为user1 我有user1创建的约会的副本user2 我有冒充权 我要编辑user2预约的副本 我怎样才能获得user2 s copy 您可以使用 PidLidClean
  • C# Julian 日期解析器

    我在电子表格中有一个单元格 它是 Excel 中的日期对象 但当它来自 C1 的 xls 类时 它会变成双精度型 类似于 2009 年 1 月 7 日的 39820 0 我读到这是儒略日期格式 有人可以告诉我如何在 C 中将其解析回 Dat
  • 参数数量在编译时确定的 Lambda 函数

    我想声明一个带有 N 个参数的 lambda 函数 其中 N 是模板参数 就像是 template
  • 如何使用 xamarin 表单提示用户进行地理定位

    我正在 Xamarin Forms 应用程序中开发一个应用程序 需要请求地理位置权限 如果获得许可 它需要从设备获取地理位置数据 然后将地理位置坐标放入 Forecast io URL 我正在使用 James 的 Geolocator 插件
  • 如何在给定点停止线程?

    我试图停止一些线程 阅读一些有关优雅地执行此操作的正确方法的内容 但我一定做错了什么 因为它根本不起作用 起初我尝试不使用lock with IsRunning不稳定 然后尝试使用锁 这是我所拥有的 private volatile boo
  • 如何在 C# 中以编程方式创建柔和的颜色?

    根据所需的颜色数量均匀分布地生成它们 如果指定的计数为 8 则看起来像这样 List
  • 如何在没有 Visual Studio 的情况下将新文件添加到 .csproj 文件

    如何添加新文件到 csproj从命令提示符 我认为没有任何工具可以响应命令行上的 add project 命令来执行此操作 但我认为您可以幸运地创建一个程序 脚本来直接操作 csproj 文件的 XML 内容 csproj 文件的结构如下所
  • 如何在用户空间程序中使用内核 libcrc32c (或相同的函数)?

    我想在我自己的用户空间程序中进行一些 CRC 检查 我发现内核加密库已经在系统中 并且支持 SSE4 2 我尝试直接 include

随机推荐

  • 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