【C++】全局变量的声明与定义

2023-10-30

编译单元(模块)

在VC或VS上编写完代码,点击编译按钮准备生成exe文件时,编译器做了两步工作:

  • 将每个.cpp(.c)和相应的.h文件编译成obj文件;
  • 将工程中所有的obj文件进行LINK,生成最终.exe文件。

那么,错误可能在两个地方产生:

  • 编译时的错误,这个主要是语法错误;
  • 链接时的错误,主要是重复定义变量等。

编译单元指在编译阶段生成的每个obj文件。

  • 一个obj文件就是一个编译单元。
  • 一个.cpp(.c)和它相应的.h文件共同组成了一个编译单元。
  • 一个工程由很多编译单元组成,每个obj文件里包含了变量存储的相对地址等。

声明与定义

函数或变量在声明时,并没有给它实际的物理内存空间,它有时候可保证你的程序编译通过;
函数或变量在定义时,它就在内存中有了实际的物理空间。
如果你在编译单元中引用的外部变量没有在整个工程中任何一个地方定义的话,那么即使它在编译时可以通过,在连接时也会报错,因为程序在内存中找不到这个变量。
函数或变量可以声明多次,但定义只能有一次

extern作用

  1. 当它与"C"一起连用时,如extern "C" void fun(int a, int b);,则编译器在编译fun这个函数名时按C的规则去翻译相应的函数名而不是C++的。(C函数不能重载)
  2. 当它不与"C"在一起修饰变量或函数时,如在头文件中,extern int g_nNum;,它的作用就是声明函数或变量的作用范围的关键字,其声明的函数和变量可以在本编译单元或其他编译单元中使用。

note:可以把全局变量的声明和定义放在一起,这样可以防止忘记了定义,如上面的extern char g_szBuffer[g_nBufferSize];然后把引用它的文件中的#include "res.h"换成extern char g_szBuffer[]; 但是这样做很不好,因为你无法使用#include "res.h"(使用它,若达到两次及以上,就出现重定义错误;注:即使在res.h中加#pragma once,或#ifndef也会出现重复定义,因为每个编译单元是单独的,都会对它各自进行定义),那么res.h声明的其他函数或变量,你也就无法使用了,除非也都用extern修饰,这样太麻烦,所以还是推荐使用.h中声明,.cpp中定义的做法

静态全局变量(static)

注意使用static修饰变量,就不能使用extern来修饰,即static和extern不可同时出现。
static修饰的全局变量的声明与定义同时进行,即当你在头文件中使用static声明了全局变量,同时它也被定义了
static修饰的全局变量的作用域只能是本身的编译单元。在其他编译单元使用它时,只是简单的把其值复制给了其他编译单元,其他编译单元会另外开个内存保存它,在其他编译单元对它的修改并不影响本身在定义时的值。即在其他编译单元A使用它时,它所在的物理地址,和其他编译单元B使用它时,它所在的物理地址不一样,A和B对它所做的修改都不能传递给对方。
多个地方引用静态全局变量所在的头文件,不会出现重定义错误,因为在每个编译单元都对它开辟了额外的空间进行存储。

全局常量(const)

const单独使用时,其特性与static一样(每个编译单元中地址都不一样,不过因为是常量,也不能修改,所以就没有多大关系)。
const与extern一起使用时,其特性与extern一样。

extern const char g_szBuffer[];      //写入 .h中
const char g_szBuffer[] = "123456"; // 写入.cpp中
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】全局变量的声明与定义 的相关文章

  • C++,多语言/本地化支持

    向 C 程序添加多语言支持的最佳方法是什么 如果可能 应该从包含键值对 WelcomeMessage Hello s 之类的纯文本文件中读取语言 我想到了添加一个 localizedString key 函数来返回加载的语言文件的字符串 有
  • OpenGL,如何独立旋转对象?

    到目前为止我的代码 void display void glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT Clear Screen And Depth Buffer glLoadIdentity
  • stl 集的 C# 等效项是什么?

    我想使用 C 将一些值存储在平衡二叉搜索树中 我查看了泛型命名空间中的集合 但没有找到与 stl 集合等效的集合 我可以使用什么通用集合 我不想存储键 值对 只是值 你可以使用HashSet http msdn microsoft com
  • 运行 C# exe 文件

    复制 为什么我的 NET 应用程序在从网络驱动器运行时会崩溃 https stackoverflow com questions 148879 why does my net application crash when run from
  • const_iterators 更快吗?

    我们的编码指南更喜欢const iterator 因为它们比正常的要快一点iterator 当您使用时 编译器似乎会优化代码const iterator 这真的正确吗 如果是的话 内部到底发生了什么使得const iterator快点 编辑
  • dlopen 或 dlclose 未调用信号处理程序

    我在随机时间内收到分段错误 我注册了信号 但发生分段错误时未调用信号处理程序 include
  • C++ 为非虚方法指定初始化

    我有 a h 如下所示 class A public void doSomething 0 然后我有 b h 如下所示 include a h class b public A public void doSomething 我只是想通过尝
  • 加载配置文件时发生错误:访问路径 c:\Program Files (x86)\... 被拒绝

    我有一个在 Windows 7 上使用 Visual Studio 2010 中的安装程序部署的应用程序 该程序在 Windows 7 和 XP 上部署并运行良好 但当我在 Windows 8 系统上部署它时 出现有关访问配置文件的错误 该
  • C语言中的array、&array、&array[0]有什么区别? [复制]

    这个问题在这里已经有答案了 在学习C语言中的数组和指针时 我很困惑 为什么ch ch ch 0 彼此相等 而sptr sptr sptr 0 却不相等 这是我的源代码 int main void char ch 7 1 2 3 4 5 6
  • 具有多重继承的不明确基数

    我正在尝试在一个大库中编写一些类的子类 我收到 基础不明确 错误 这是该问题的一个可编译示例 include
  • C++头文件问题

    我在处理类时尝试了一些 C 代码 这个问题出现在我身上 并且让我有点烦恼 我创建了一个包含类定义的头文件和一个包含实现的 cpp 文件 如果我在不同的 cpp 文件中使用此类 为什么要包含头文件而不是包含类实现的 cpp 文件 如果我包含类
  • 向窗口句柄发送消息

    我尝试使用 sendmessage 将消息从我的 C 应用程序传递到 C 我的c 代码是这样的 int tmain int argc TCHAR argv COPYDATASTRUCT cpd cpd dwData 0 LPCWSTR st
  • 为什么 C++ 元组如此奇怪?

    我通常创建自定义structs将不同类型的值分组在一起时 这通常很好 而且我个人发现命名成员访问更容易阅读 但我想创建一个更通用的 API 在其他语言中广泛使用元组后 我想返回类型的值std tuple但发现它们在 C 中使用比在其他语言中
  • 将纬度/经度转换为 X/Y,以便在美国地图图像上进行阿尔伯斯投影

    我正在尝试使用 C 或 Javascript 将纬度 经度转换为 X Y 坐标 以将带有 CSS 的 div 左 上 定位到美国地图的背景图像上 美国的标准地图投影是阿尔伯斯投影 如下所示 但 StackOverflow 仅提供参考基本墨卡
  • 我们可以使用 C# 录制发送到扬声器的声音吗

    我有一个软件 SoundTap Streaming Audio Recorder 它记录发送到扬声器的任何音频 无论流是来自网络还是来自某些文件或麦克风 我可以在桌面应用程序中制作这样的应用程序 以便我可以录制发送到扬声器的流 无论来源如何
  • 在运行时将项目添加到 ToolStrip

    您好 我有一个带有 收藏夹 菜单的 ToolStripMenu 我想在运行时在 WinForms 应用程序中添加子项目 我有一个 datagridview 右键单击它会显示一个包含 添加到收藏夹 选项的上下文菜单 当该事件被触发时 我想使用
  • 使用 /clr 或 clr:pure(cpprestsdk 又名 casablanca)编译时不支持互斥

    我创建一个CLR project in visual c with 64 bit配置 并尝试使用cpprestsdk aka casablanca 64bit 但是当我运行项目时 出现了错误 1 gt Build started Proje
  • 我应该为每个 Web 请求使用静态缓存的 ResourceManager 还是一个新实例?有关系吗?

    创建新的 NET 对性能 或其他 有何影响 如果有 ResourceManager根据每个请求new ResourceManger myResourceType FullName myResourceType Assembly 与在 Des
  • InvalidOperationException:没有为方案“CookieSettings”注册身份验证处理程序

    我正在使用 ASP Net MVC core 2 1 开发一个应用程序 其中不断出现以下异常 InvalidOperationException 没有为方案 CookieSettings 注册身份验证处理程序 注册的方案有 Identity
  • 如何使用 __m128i 执行元素左移?

    我发现 SSE 移位指令只能在所有元素上移位相同的量 mm sll epi32 mm slli epi32 这些会移动所有元素 但移动量相同 http software intel com sites products documentat

随机推荐

  • Python函数和模块运用实践

    1 函数的定义与调用 函数名尽量用英文单词命名 并且容易识别意思 函数的形参有4中类型的参数 位置参数 指定参数 缺省参数和不定长参数 在python实践过程中用的最多的是不定长参数 不定长参数方便代码重构 def introduction
  • 使用Clion开发STM32过程中的提示:此文件不属于任何项目目标,代码洞察功能可能无法正常工作(附带汉化方法)

    Catalog 一 问题描述 二 解决办法 三 附带Clion汉化方法 一 问题描述 笔者在学习STM32开发过程中 在使用CubeMX生成工程文件后 又新建了自己的User文件 在编译的过程中终端会提示 在文件中会提示 并且笔者检查代码确
  • SQLite基本操作

    SQLite SQLite是一个软件库 实现了自给自足的 无服务器的 零配置的 事务性的 SQL 数据库引擎 SQLite 源代码不受版权限制 SQLite 直接访问其存储文件 SQLite 是非常小的 是轻量级的 完全配置时小于 400K
  • Git安装与配置

    1 Git安装与配置 1 1 什么是Git Git是目前世界上最先进的分布式版本控制系统 Git是免费 开源的 最初Git是为辅助 Linux 内核开发的 来替代 BitKeeper 作者 Linux和Git之父李纳斯 托沃兹 Linus
  • Java用JDBC通过远程连接PostgreSQL并实现操作

    工具及准备介绍 1 本文使用的开发软件是eclipse1 7 2 需要下载postgresqlpostgresql 9 2 1002 jdbc3 jar 需要的话在我的资源上下载 需要数据库管理软件Navicat 3 本文是用JDBC连接数
  • CSDN中如何转载他人的博客

    1 复制他人博客内容 打开需要转载的博客文章 在页面任意空白处点击鼠标右键 gt 检查 打开浏览器开发模式页面 在元素中找到名为article content的div 选中后右击 gt 复制 gt 复制 outerHTML 2 新写博客文章
  • 理想倍频器/分频器对相噪/杂散的影响

    结论 使用理想倍频器将信号频率提高 N N倍 会让相噪抬高 20log 10 N 20log 10 N dB 类似的 N N分频会让相噪降低 20log 10 N 20log 10 N dB 理想倍频器 对于信号 f t cos t t f
  • Stegsolve.jar工具包准备,避坑指南,教你正确启动Stegsolve

    目录 准备阶段 错误重现 错误分析 Stegsolve jar正确启动方法 准备阶段 下载地址 http www caesum com handbook Stegsolve jar 环境配置的过程 3分钟复制粘贴配置java环境变量 验证配
  • [Unity]有关curson/鼠标的详细AIP

    Unity 有关curson 鼠标的详细AIP 经常用到的与curson有关的API Cursor lockState Cursor lockState CursorLockMode None 光标行为未修改 Cursor lockStat
  • MySQL秘籍:让你的表操作炉火纯青

    每个人都有自己的一生 不要和别人去比较 比较只会让你感到沮丧和不满足 关注自己的成长和进步 并享受属于自己的旅程 作者 不能再留遗憾了 专栏 MySQL学习 本文章主要内容 学习MySQL的对表操作 查看表 创建表 删除表 对表进行增删改查
  • Vue 实现生成二维码(qrcodejs2),并生成图片(html2canvas)可实现保存和识别

    1 引包 npm install qrcodejs2 save npm install save html2canvas import html2canvas from html2canvas import QRCode from qrco
  • 传送文件到云服务器,传送文件到云服务器

    传送文件到云服务器 内容精选 换一换 安装传输工具在本地主机和Windows云服务器上分别安装数据传输工具 将文件上传到云服务器 例如QQ exe 在本地主机和Windows云服务器上分别安装数据传输工具 将文件上传到云服务器 例如QQ e
  • Linux基础笔记4

    绝对路径 以根目录为参照物 从根目录开始 一级一级进入目录 相对路径 以当前目录作为参照物 进行目录查找 1 1 目录操作 ls 显示目录下的内容 查看 etc passwd文件 文件夹下的信息 ls l etc passwd 查看当前文件
  • zookeeper连接,报caught end of stream exception EndOfStreamException: Unable to read additional data fro

    最近发现线上的zookeeper的日志zookeeper out 文件居然有6G 后来设置下日志为滚动输出 但是改了之后 发现一天的日志量就是100多M 滚动日志一天就被冲掉了 这个不科学 再仔细查看下日志里的内容 发现有很多连接建立好 马
  • C++ std::remove/std::remove_if/erase用法探讨

    std remove 不会改变输入vector string的长度 其过程相当于去除指定的字符 剩余字符往前靠 后面的和原始字符保持一致 需要注意的是 remove函数是通过覆盖移去的 如果容器最后一个值刚好是需要删除的 则它无法覆盖掉容器
  • 强化学习的状态值函数与状态动作值函数

    在本文中 我们将学习贝尔曼方程和价值函数 回报和返还 return 正如前面所讨论的 强化学习agent如何最大化累积未来的回报 用于描述累积未来回报的词是返还 通常用R表示 我们还使用一个下标t来表示某个时间步长的返还 在数学符号中 它是
  • sql:查询创建表的结构

    显示所有用户表 1 SELECT SCHEMA NAME schema id As SchemaName name As TableName from sys tables ORDER BY name 2 alternate SELECT
  • QML android 采集手机传感器数据 并通过udp 发送

    利用 qt 开发 安卓 app 采集手机传感器数据 并通过udp 发送 ifndef UDPLINK H define UDPLINK H include
  • 数据结构与算法(非常详细)从零基础入门到精通,看完这一篇就够了

    本文包含数据结构与算法主要的基本知识点 便于知识的梳理与回顾 部分知识点的详细介绍请在专栏内查阅 目录 一 概述 二 线性表 三 栈 四 队列 五 串 六 多维数组和广义表 七 树和二叉树 八 图 九 查找 十 排序 一 概述 数据结构 逻
  • 【C++】全局变量的声明与定义

    文章目录 编译单元 模块 声明与定义 extern作用 静态全局变量 static 全局常量 const 编译单元 模块 在VC或VS上编写完代码 点击编译按钮准备生成exe文件时 编译器做了两步工作 将每个 cpp c 和相应的 h文件编