C++中的extern

article/2025/9/24 13:38:53

文章目录

    • extern的含义
      • 修饰全局变量
      • 修饰全局常量
      • 修饰局部变量
      • 修饰字符串
        • C++代码
        • C代码

想必大家都知道,在C++中,想要生成一个可执行文件(exe)或者动态链接库(dll),需要经过编译和链接两个步骤,C++里面的变量也比C#分的更加细致,包括了声明和定义两个不同阶段。这些迥然不同于C#的细节,让很多从C#转向C++的程序员在学习伊始非常头疼。特别对于C++里的关键字extern,和它在不同上下文的不一样的含义,让很多程序员直呼好家伙。今天,就让我们聊聊它吧。

extern的含义

按照语法书的说法,extern一般有如下用途。

  • 修饰全局变量:在声明全局变量的时候使用extern修饰变量,表明该变量定义于其他翻译单元。
  • 修饰全局常量:表明该全局常量拥有外部链接(可以被其他翻译单元发现),否则全局常量默认是只有内部链接,即不可被其他翻译单元发现。
  • 修饰局部变量:表明该局部变量在其他翻译单元中被定义,需要在链接的时候去解析。
  • 修饰一个字符串:形如extern “C” 之类的用法大家肯定见过了,表明后接的代码块(或者后接的声明)使用C语言调用惯例。
  • 修饰一个模板:表明该模板已经在其他翻译单元实例化,不需要在这里实例化。

因为模板是一个很大的内容,extern修饰模板的使用今天暂且不谈,以后讲到模板的时候再说。我们重点谈谈前面几个含义。

修饰全局变量

如果想表明某个全局变量来自其他翻译单元,可用extern修饰,但如果此语句是一个变量定义,那么extern将被忽略。比如:

//file1
int i = 0; //默认拥有外部链接
extern int j; //j定义于其他翻译单元
extern int i = 10; //与 int i = 0 相同,这里extern被忽略,属于重复定义

请注意,对于全局变量,如果语句中没有extern也没有显示赋值,编译器(在VS2017中实测)会帮忙初始化变量为0,这种情况会视为变量定义,但是却不会与之后的变量定义发生冲突,所以这么写是可以的

//file1
int i; //编译器会帮忙初始化0
extern int i = 10; //第二次变量定义,但是这里却是允许的,变量变成了10

 

修饰全局常量

全局常量默认没有外部链接,所以extern的主要在于分享全局常量给其他翻译单元。

//file1
extern const int J = 10; //定义拥有外部链接的全局常量J//file2
extern const int J; //声明全局常量J来自于其他翻译单元

 

修饰局部变量

对于局部变量来说,extern可用于声明该局部变量来自其他翻译单元,但是不能使用extern定义一个拥有外部链接的局部单元

void Test()
{extern int i; //表明i来自于其他翻译单元extern int j = 20; //错误,因为局部变量的生命周期在退出函数的时候就结束了,所以不允许其建立外部链接
}

 

修饰字符串

C++向下兼容C,所以C++需要提供一种方式能和C代码互动。说起来应该是很简单的一件事,因为他们的语法都是一样的嘛,让我们试试(以下还是以vs2017为例)
 

C++代码

建立一个静态链接库,里面包含一个简单的方法Sum

//sum.cpp
int Sum(int i, int j)
{return i + j;
}

顺利编译成lib
 

C代码

建立一个C工程,创建一个main文件并使用刚刚建立的C++库。

//main.c
#include <stdio.h>int Sum(int i, int j); //函数声明int main(void)
{int result = Sum(1, 2); //使用函数return 0;
}

在工程属性中选择用C编译器,确保以C的惯例进行编译。
在这里插入图片描述
之后设置链接参数,确保链接器能拿到C++的lib。之后试着Build。
在这里插入图片描述
啊哦,链接器报错了,这是为什么呢?

究其原因,和C calling convention有关,我们都知道在C中没有函数重载,所以C的编译器一般不会把函数名重新编码(name mangling),而C++会把函数的参数,返回值甚至命名空间一起当做原材料,生成一个name mangling之后的字符串当做链接器里面的函数名字。所以这里C期望得到的Sum名字和C++那边提供的Sum名字对不上,也就自然找不到了。

要想解决这个问题,我们就需要以C的命名惯例编译C++库。修改代码如下:

//sum.cpp
extern "C"
{int Sum(int i, int j){return i + j;}
}

再次build,这次就一切正常了。所以大家可以知道extern 加字符串的作用了吧。类似的,如果是用C++代码调用C库,我们也可以使用extern "C++"来编译C库。但是请注意,在extern "C"里面需要严格遵守C规定,函数重载等是不被支持的。

关于Calling Convention和Name Mangling,也是一个比较大的话题,感兴趣的同学可以进一步在这里进行深入阅读。

 
从C#到C++的跨越需要非凡的努力,有非常多的东西要学,extern只是其中一个很小的知识点却也可见一斑,C++之于C#,难点在于更底层更强大,也就需要更多的耐心去研究,extern当时也困惑了我很久,希望通过这篇博客,能让和当时的我一样迷茫的朋友少走弯路。

希望大家喜欢,也希望大家点赞关注,跟着老胡一起学习C++。


http://chatgpt.dhexx.cn/article/4X8pmnSP.shtml

相关文章

extern使用方法总结!

一、问题 Extern的问题在于不知道这个关键词出现的时候到底是声明还是定义&#xff1f; 二、详解 1、函数的声明extern关键词是可有可无的&#xff0c;因为函数本身不加修饰的话就是extern。但是引用的时候一样需要声明的。 2、全局变量在外部使用声明时&#xff0c;extern关键…

extern详解

extern——关键字 extern是C语言中的一个关键字&#xff0c;一般用在变量名前或函数名前&#xff0c;作用是用来说明“此变量/函数是在别处定义的&#xff0c;要在此处引用”&#xff0c;extern这个关键字大部分读者应该是在变量的存储类型这一类的内容中 遇到的&#xff0c;…

【014 关键字】一文彻底搞懂extern用法

一、定义和声明的区别 声明&#xff1a;用来告诉编译器变量的名称和类型&#xff0c;而不分配内存&#xff0c;不赋初值。 定义&#xff1a;为了给变量分配内存&#xff0c;可以为变量赋初值。 注&#xff1a;定义要为变量分配内存空间&#xff1b;而声明不需要为变量分配内…

HDU AWR电磁场与微波实验 操作记录

类型 滤波器版图设计功放设计IV曲线创建偏置电路&添加原理图背面注释添加谐波平衡端口添加双音激励端口 实验课需要使用这款软件 记录一下&#xff0c;提醒自己如何操作 工程文件如下 &#xff0c;0积分 滤波器. 版图. 功放. 交指滤波器. 滤波器 • Creating a schematic …

达梦AWR使用

DBMS_WORKLOAD_REPOSITORY 包 1、概述 AWR默认是关闭的需要受到开启&#xff0c;如 果 需 要 开 启 &#xff0c; 则 调 用 DBMS_WORKLOAD_REPOSITORY.AWR_SET_INTERVAL 过 程 设 置 快 照 的 间 隔 时 间 。 DBMS_WORKLOAD_REPOSITORY 包还负责 snapshot&#xff08;快照&…

AWR(性能报告)

本文章为网络笔记&#xff0c;看了warehouse老师的视频受益匪浅&#xff0c;更是感觉自己技术太过初级&#xff0c;特写了本笔记&#xff0c;方便以后反复学习&#xff01; 如有任何不妥&#xff0c;请发邮件至102448567qq.com删除文章&#xff01; 关于warehouse&#xff1a; …

AWR2243

TDA2xx-AWRx243 TI毫米波板&#xff08;代完善更新和作者的继续研究&#xff09; 1、安装mmwave studio和驱动&#xff08;链接&#xff1a; https://download.csdn.net/download/weixin_42501561/19775644 &#xff09; 2、设置网络端口IP地址&#xff08;如果不能更改路由器I…

awr报告

某客户反馈数据库慢&#xff0c;给到一份awr报告。分析如下 每个cpu可用处理时间3501.6s(59.86min)&#xff0c;系统负载为&#xff1a;511(59.86*16)50%,其中16为CPUs direct path read最高&#xff0c;可能有下面三种原因&#xff1a; parallel query大量disk排序table预读取…

awr清理

Oracle并没有真正进行删除AWR报告信息&#xff0c;查询metalink发现是Oracle的bug&#xff0c; Bug 8622802描述了这个问题&#xff0c; 修复版本&#xff1a; #禁用awr报告 EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(INTERVAL > 0); select * from WRM$_SN…

AWR

AWR自动工作量资料档案库: AWR用于收集关于该特定数据库的操作统计信息和其他统计信息&#xff0c;oracle以固定的时间间隔&#xff08;默认60分钟&#xff09;为其所有重要统计信息和负载信息执行一次快照&#xff0c;并将这些快照存储在AWR中。这些信息在AWR中保留给定的时间…

达梦 awr

AWR 全称为自动工作集负载信息库&#xff08;Automatic Workload Repository&#xff09; ,采集数据库的性能相关数据,用来分析数据库性能问题,方便调优工作。 达梦中 awr 功能默认是关闭的,另外 mpp 集群不支持 awr 开启 AWR 功能 检查 awr 开启状态 达梦提供了 SF_CHECK_AW…

ORACLE调优深入理解AWR报告

什么是AWR? 一堆历史性能数据&#xff0c;放在sysaux表空间上&#xff0c;AWR和sysaux都是10g出现的&#xff0c;是oracle调优的关键特性。 默认快照间隔1小时&#xff1b;10g保存7天&#xff1b;11g保存8天&#xff1b; 可以通过DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SE…

AWR射频仿真基本操作(一)

这里只讲述一个基本的操作&#xff1a; 软件是AWR 14版本 新建工程 File–New project 然后File-project as 即另存为新建一个工程&#xff0c;自己取好名字。 设置基本参量 AWR可以直接进行仿真频率和单位之类的基本设置。 如果你只需要基本的S参数仿真&#xff0c;那么…

理论实践:循序渐进理解AWR细致入微分析性能报告

理论实践&#xff1a;循序渐进理解AWR细致入微分析性能报告 黄凯耀 (Kaya) ACOUG核心会员&#xff0c;高级技术专家 曾经工作于Oracle Real World Database Performance Group&#xff0c;一个隶属于Oracle公司总部数据库产品管理的核心团队。大学及研究生时期专注于Linux应用开…

AWR概念原理涉及表和包

一&#xff1a;AWR概念 Oracle10g以后&#xff0c;Oracle提供了一个性能检测的工具&#xff1a;AWR&#xff08;Automatic Workload Repository 自动工作负载库&#xff09;这个工具可以自动采集Oracle运行中的负载信息&#xff0c;并生成与性能相关的统计数据。我们可以根据这…

三种编码方式(费诺曼编码,霍夫曼编码,哈夫曼树编码)的简单解释和介绍

一. 费诺曼(Fano)编码是一种前缀编码&#xff0c;其基本原理是将出现频率较高的符号用短的编码表示&#xff0c;而出现频率较低的符号则用长的编码表示。通过这种方式进行编码&#xff0c;可以达到更好的压缩效果。 费诺曼编码的具体过程如下&#xff1a; 将要编码的符号按照…

霍夫曼编码及解码(简单实现)

霍夫曼树 霍夫曼树又称最优二叉树&#xff0c;是一种带权路径长度最短的二叉树。 所谓树的带权路径长度&#xff0c;就是树中所有的叶结点的权值乘上其到根结点的路径长度&#xff08;若根结点为0层&#xff0c;叶结点到根结点的路径长度为叶结点的层数&#xff09;。 树的路…

霍夫曼树和霍夫曼编码原理

一、哈夫曼树的概念和定义 什么是哈夫曼树&#xff1f; 让我们先举一个例子。 判定树&#xff1a; 在很多问题的处理过程中&#xff0c;需要进行大量的条件判断&#xff0c;这些判断结构的设计直接影响着程序的执行效率。例如&#xff0c;编制一个程序&#xff0c;将百分制转换…

学习笔记--霍夫曼树与霍夫曼编码解码

先摘一下百科的说法 “哈夫曼编码(Huffman Coding)&#xff0c;又称霍夫曼编码&#xff0c;是一种编码方式&#xff0c;哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法&#xff0c;该方法完全依据字符出现概率来构造异字头的平均长度最短的码字&#x…

霍夫曼编码的matlab实现

霍夫曼编码的原理已经有很优秀的介绍博客了&#xff0c;给出现频率高的灰度级分配更短的码字无非就是利用数学中逆序乘积和最小的原理&#xff0c;具体的原理介绍我就不再赘述了。这里给大家分享一下我个人早先实现的霍夫曼编码matlab程序。废话不多说&#xff0c;直接上代码&a…