C++| extern外部变量的使用 | 与全局静态变量的区别 | C++ Windows多文件编译运行 | 多个源文件共用一个全局变量

C++全局变量重复定义:从编译链接原理到工程实践解决方案 在C++程序开发中,编译与链接是构建可执行文件的两个核心阶段。编译器以翻译单元为单位处理源代码,生成目标文件;链接器则负责解析跨文件的符号引用,将多个目标文件合并为最终程序。这一过程遵循“一次定义规则”,要求每个具有外部链接属性的符号在程序中必须有且仅有一个定义。理解声明与定义的区别、内部链接与外部链接的机制,对于构建健壮的多文件项目至关重要。全局变量的重复定义错误是这一领域的典型问题,常因在头文件中直接定义变量或错误处理类静态成员导致。通过extern声明配合单一定义、使用匿名命名空间赋予内部链接、或采用 阅读详情


网上检索关于extern相关内容时,自己尝试过程中,发现有一些区别,不知道是不是版本问题,特此记录

区别

  1. 全局变量是不显式用 static 修饰的全局变量,全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过 extern 全局变量名的声明,就可以使用全局变量。
  2. 全局静态变量是显式用 static 修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用 extern 声明也不能使用。

外部变量extern使用

extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义,避免出现重定义。

我查看很多博客均说,需要在“别”的文件用extern申明变量,我尝试的时候,可以不申明直接使用;(g++版本8.1.0)

  • ExternTest.h
#ifndef _EXTERN_TEST_H_
#define _EXTERN_TEST_H_
extern int i;
void func1();
#endif
  • ExternTest.cpp

#include"ExternTest.h"
#include <iostream>
int i=1;
void func1(){
    std::cout<<i<<std::endl;
    i++;
}
  • MainTest.cpp
#include"ExternTest.h"
#include<iostream>
//extern int i;//可以不声明
void func2(){
    std::cout<<i<<std::endl;
}
int main(){
    func1();
    func2();
    func1();
    func2();
    //输出
    /**
    1
    2
    2
    3   
    */
}
/**
 * 运行命令
 * g++ -c ExternTest.cpp
 * g++ -c MainTest.cpp
 * g++ MainTest.o ExternTest.o -o test
 * ./test.exe
 * */

全局静态变量static使用

  1. 静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量;
  2. 未经初始化的静态全局变量会被程序自动初始化为0(在函数体内声明的自动变量的值是随机的,除非它被显式初始化,而在函数体外被声明的自动变量也会被初始化为 0);
  3. 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的。
  • 优点:静态全局变量不能被其它文件所用;其它文件中可以定义相同名字的变量,不会发生冲突。

  • StaticTest.h

#ifndef _STATIC_TEST_H_
#define _STATIC_TEST_H_
static char str[]="123456";
void func1();
#endif
  • StaticTest.cpp
#include"StaticTest.h"
#include<iostream>
void func1(){
    str[0]='h';
    std::cout<<str<<std::endl;
}
  • MainTest.cpp
#include"StaticTest.h"
#include<iostream>
void func2(){
    std::cout<<str<<std::endl;
}
int main(){
    func1();
    func2();
    /**
     * h23456
     * 123456
     * */
    return 0;
}
/*
g++ -c StaticTest.cpp
g++ -c MainTest.cpp
g++ MainTest.o StaticTest.o -o test
./test.exe
C++工程化实践:多文件编程、编译链接与调试技巧详解 在C++开发中,多文件编程是实现代码模块化和可维护性的基础技术。其核心原理在于通过头文件与源文件的职责分离,构建编译防火墙,从而提升编译效率并降低代码耦合度。这一技术价值在于将学生作业式的单一文件思维,转变为适用于大型软件工程的模块化架构,是C++开发者从语法学习迈向工程实践的关键一步。在实际应用场景中,多文件编程需要配合头文件守卫、合理的include策略以及清晰的目录结构,才能有效管理复杂项目。本文围绕C++工程化这一主题,深入探讨了编译与链接的底层机制,并分享了包括数据断点、条件断点在内的高效调试技巧 阅读详情

相关推荐

在windows下编译某linux源码

最近编译了一份linux下写的源码,源码中并无跨平台相关的代码,因此win下无法直接编译,而且源码较多,在linux下./configure 后make,make install很容易就编译并使用。 但由于要求把该linux源码编译成win下的库在VS中调用,所以煞费工夫,总结一些东西,以免忘了。。。 cygwin 或者 msys2、mingw 下 ./configure make

曙光的学习之路 4918

C/C++中的extern的使用

C++ extern的介绍和说明

lihaizhen0507的博客 9281

Windows下MinGW-w64环境搭建与g++命令行编译实战指南

C++编译环境是开发者从源代码到可执行程序的关键桥梁,其核心在于编译器将高级语言转换为机器码的翻译过程。GCC作为GNU编译器集合,通过其C++前端g++实现了跨平台的代码编译能力,为开发者提供了对构建流程的完全控制权。在Windows平台,MinGW-w64作为GCC的移植版本,提供了纯净的命令行工具链,避免了与特定IDE的深度绑定,特别适合学习标准C++、理解编译链接原理以及追求跨平台兼容性的开发场景。本文聚焦于MinGW-w64的选型安装、系统环境变量配置以及g++编译器的实战应用,通过详解多文件项目

weixin_34268843的博客 488

C++外部变量定义与使用

不同于Java与C#, C++的变量与函数不一定存在于类中. 在C++中, 定义于函数外的变量称为外部变量, 函数内的变量称为局部变量, 也叫自动变量. 外部变量只能被定义一次, 而且在函数内对外部变量的引用必须进行声明, 可用extern语句进行显示声明, 也可以上下文隐式声明, 假如在函数内定义了与外部变量名称相同的变量, 则不会使用外部变量, 而是以当前定义变量使用. 如图 在main函数...

weixin_44573776的博客 1万+

C++多重定义错误全解析:从ODR规则到工程实践解决方案

在C++编程中,编译与链接是构建可执行程序的两个关键阶段。编译阶段将每个源文件独立转换为目标文件,而链接阶段则负责合并所有目标文件并解析符号引用。理解声明与定义的区别至关重要:声明引入符号名而不分配存储空间,可多次出现;定义则创建符号并分配存储空间,在整个程序中必须唯一。违反这一原则会导致链接器报出多重定义错误,严重影响项目构建效率。这一问题的核心在于C++的一次定义规则(ODR),它要求任何变量、函数或类型在程序中只能有一个定义。从技术价值看,掌握ODR不仅能解决编译错误,更是构建大型、模块化C++项目的

weixin_30475039的博客 442

VC++ 2015 Build Tools:Windows C++命令行编译与CI/CD构建实战指南

在Windows平台进行C++开发时,编译器工具链是构建项目的核心基础。Visual C++ Build Tools作为微软提供的独立编译环境,包含了cl.exe编译器、link.exe链接器等核心组件,其工作原理是通过配置环境变量(如PATH、INCLUDE、LIB)来定位头文件和库,实现源代码到二进制文件的转换。这项技术的价值在于提供了轻量级、可脚本化的构建方案,尤其适用于持续集成(CI/CD)流水线、自动化构建服务器以及追求环境纯净的命令行开发场景。对于需要编译历史遗留项目或特定版本第三方库(如Ope

jardownload的博客 374

c++ extern的用法【转载】

现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。这两个文件极为简单,在A.cpp中我们定义了一个全局变量i,在B中我们也定义了一个全局变量i。这就是说,在编译阶段,各个文件中定义的全局变量相互是透明的,编译A时觉察不到B中也定义了i,同样,编译B时觉察不到A中也定义了i。

max的博客 849

5分钟搞懂知识抽取:如何把非结构化数据变成知识图谱的宝藏?

本文通过一个电商评论分析实战案例,详细解析了如何利用spaCy、Neo4j等工具,将非结构化文本数据转化为结构化知识图谱的完整流程。文章重点阐述了知识抽取的核心步骤,包括命名实体识别、关系抽取以及知识存储与查询,帮助读者快速掌握将数据转化为知识宝藏的关键技术。

weixin_29054245的博客 233

C++:外部变量和静态变量

外部变量的定义和声明是不同的。外部变量的定义只能有一次,它的位置在所有函数之外,而统一文件中的外部变量的声明可以有多次,它的位置可以在函数之内,也可以在函数之外。 系统根据外部变量的定义,而不是声明,分配存储单元。对外部变量的初始化,只能在定义时进行,而不能在声明中进行。关于全局变量(作用域在全局,可跨.cpp) 在x.h中定义一个结构体类型mem_data,将其包含在1.cpp中,则可在1.cp...

Moomin的博客 2406

Xilinx实战-深入AXI UART Lite IP核的配置与调试

本文详细介绍了Xilinx FPGA中AXI UART Lite IP核的配置与调试方法,包括Vivado环境下的IP核设置、关键参数优化、寄存器操作及常见问题排查。通过实战案例和代码示例,帮助开发者快速掌握AXI接口的串口通信技术,提升嵌入式系统开发效率。

weixin_29189377的博客 225

手把手教你用STM32标准库写一个能OTA升级的Bootloader(附完整代码)

本文详细介绍了如何使用STM32标准库开发支持OTA无线升级的Bootloader系统,包括Flash分区规划、Bootloader核心实现、无线升级流程及安全校验机制。通过实战代码示例,帮助开发者快速掌握STM32固件升级技术,提升物联网设备的远程维护能力。

weixin_30181209的博客 262

C++中extern关键字详解:不同情况下的使用方式

C++中extern关键字详解:不同情况下的使用方式

qq_45166271的博客 1125

AB相增量式编码器以及STM32定时器编码器模式测速/测距离(HAL库)

编码器(Encoder)是一种用于测量旋转运动或位置的设备。编码器通常与定时器模块一起使用,以便在微控制器中获取和计算旋转的脉冲数量,从而确定物体的运动方向和距离。编码器在许多应用中都很有用,例如机器人运动控制、电机位置反馈和位置传感。STM32微控制器提供了多种类型的编码器支持,其中一种常见的编码器类型是增量编码器。增量编码器基于两个脉冲信号通道,通常称为A相和B相。当旋转发生时,这两个信号通道的相位关系会发生变化,从而可以计算出旋转方向和旋转的步数。

嵌入式软件工程师的博客 1万+

Windows的cmd运行编译器(cmd运行c/c++、python等)

文中主要讲述了cmd简介,cmd运行编译器gcc/g++执行C/C++程序代码,gcc与g++的区别及其使用注意事项,extern "C",重载函数(函数重载),cmd运行python解释器执行python程序代码。

Python基础详解教程,让编程变得简单! 1万+

从零构建:如何在VSCode中为HBuilderX迁移的UniApp项目搭建TypeScript支持环境

本文详细指导如何将HBuilderX中的UniApp项目迁移至VSCode并搭建TypeScript支持环境。通过pnpm包管理器初始化项目、配置tsconfig.json和vite.config.ts文件,实现工程化迁移与TypeScript深度集成,提升开发效率和代码质量。

book8的博客 1050

Dr_can Kalman Filter学习笔记(一)

本文是在b站Dr_can的卡尔曼滤波课程学习过程中的学习笔记

苏大侠的博客 1051

编译器对extern的处理

1、 声明外部变量         现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。 创建一个工程,里面含有A.cpp和B.cpp两个简单的C++源文件: //A.cpp  int i;  void main()  {  } //B.cpp

wuzhenle的专栏 738

FastAPI + React:现代 Web 前后端分离开发的全栈实践指南

• 部署:CI/CD 双流水线,前端 push → GitHub Actions → Cloudflare Pages;• 后端:分层结构 routers → services → repositories → models,单测覆盖率 90 %。• 接口缓存:Redis + FastAPI Depends 实现接口级缓存,读 QPS 提升至 5 k。• 前端:BFF 由 React Query 代理,统一缓存、重试、分页。GET /items/{id} 详情。,前端同学无需等 Mock 即可联调。

未来已来,AI时代,学AI编程,做AI量化,就来大鹏AI教育。 1489

动态库导出符号与extern “C“

根据C/C++语法规则,函数声明中的修饰符(如__declspec(dllexport))可以放在返回类型之前或返回类型之后、函数名之前。这两种方式在功能上是等价的,编译器会以相同的方式处理。注:声明函数/类的 签名和导出属性(如 extern “C” 或 __declspec(dllexport)),告知编译器按特定规则生成符号名。编译器在处理 CPP 文件时,会根据头文件声明自动应用导出规则,无需在实现中重复指定。

憧憬,思考,奋斗,飞翔 696

华为OD机考双机位C卷 - 采购订单 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 采购订单 。提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 426

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C++变量重复定义:从ODR原理到现代解决方案全解析

在C++编程中,编译链接模型是理解程序构建过程的核心概念。单一定义规则(ODR)要求每个具有外部链接的实体在程序中只能定义一次,这是编译器与链接器协同工作的基本原理。违反ODR会导致multiple definition链接错误,影响代码的可维护性和跨模块协作。从技术价值看,掌握声明与定义的区别、内部与外部链接机制,是编写健壮、可复用C++代码的基础。这些知识在大型项目开发、库设计和跨平台移植等应用场景中尤为重要。本文聚焦于头文件陷阱和全局变量管理等常见痛点,通过分析extern声明、static关键字和C

weixin_34174322的博客 363

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Windows下MinGW与g++环境配置及C++编译入门指南

C++编译器是程序开发的核心工具,负责将高级语言源代码转换为机器可执行的二进制代码。其工作原理通常包括预处理、编译、汇编和链接四个关键阶段,确保代码语法正确并解析所有依赖关系。在技术价值上,一个稳定高效的编译环境不仅能提升开发效率,更是学习现代C++特性、进行跨平台项目开发的基础。尤其在Windows平台上,MinGW-w64作为GNU工具链的移植版本,为开发者提供了接近Linux环境的命令行编译体验,这对于使用Qt、OpenCV等开源框架或进行VTK等科学计算库的开发至关重要。本文聚焦于MinGW-w64

weixin_30522095的博客 376

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

【C/C++基础】extern “C“ __declspec(dllexport)详解

具体请阅读blog。

All_In_gzx_cc的博客 7021

C++多文件编程实战:从Hello World到模块化项目构建

在C++编程中,理解程序的组织结构是迈向工程化开发的关键一步。程序结构不仅关乎代码的可读性,更直接影响编译效率和项目可维护性。其核心原理在于分离声明与定义,通过头文件(.h/.hpp)提供接口声明,源文件(.cpp)实现具体功能,main函数作为程序入口。这种模块化设计的技术价值在于提升代码复用性、便于团队协作和降低维护成本。在实际应用场景中,无论是开发计算器、学生管理系统还是游戏引擎,良好的多文件组织都是基础。本文以**头文件**和**源文件**的协作为例,深入解析C++项目从单文件到多文件的演进过程,帮

ckkay800264的博客 338

C++模板编译模型解析与多文件项目实战指南

泛型编程是现代C++实现代码复用与类型安全的核心范式,其核心机制是通过模板在编译期生成类型特定的代码。模板的工作原理基于编译器的实例化机制,编译器根据调用时提供的具体类型参数,从模板蓝图生成对应的函数或类代码。这一特性使得开发者能够编写高度通用且类型安全的算法与数据结构,显著提升代码的复用性和可维护性。然而,模板的编译模型——特别是“按需实例化”机制——也带来了独特的工程挑战,尤其是在多文件项目中组织代码时,常因定义不可见而导致链接错误。理解模板的声明与定义必须对使用它的编译单元可见这一原则,是解决此类问题

weixin_34101229的博客 447

C语言头文件与源文件:从编译报错到模块化编程实践

在C语言编程中,头文件与源文件的分离是模块化设计的核心基础。头文件负责声明函数原型、宏定义和外部变量,为编译器提供类型检查的依据;源文件则承载具体的函数实现和变量定义。这种声明与定义分离的机制,不仅提升了编译效率——修改实现只需重编译单个源文件,更实现了接口的抽象封装,是大型项目协作开发的基石。通过理解#include的文本替换本质和编译单元的独立性,开发者能有效解决'undefined reference'、'重复定义'等常见编译链接问题。本文以工程实践为导向,深入解析头文件守卫、extern关键字、静态

weixin_30616969的博客 397
上一篇: Linux 修改ssh端口 | Bind to port 2222 on 0.0.0.0 failed: Permission denied
下一篇: 华为笔试2021.9.11
stone_fall
博客等级 码龄9年 230粉丝 256原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值