当前位置: 首页 > web >正文

【C++】extern

本文介绍一些externC++中的用法

声明与定义分离

C++程序员应该都知道单一定义规则ODR

在任何一个翻译单元中,只允许存在任何变量、函数、类类型、枚举类型 、概念 (自 C++20 起) 或模板的一个定义(其中一些可能具有多个声明,但只允许一个定义)。 在整个程序(包括任何标准库和用户定义的库)中,需要出现每个非 内联 函数或变量的一个且仅一个定义,这些函数或变量是 odr-使用 的(见下文)。 编译器不要求诊断此违规行为,但违反它的程序的行为是未定义的。

具体来说,如果在头文件中初始化一个变量,在多个源文件包含此头文件,在联合编译时,就会报重定义的错误。

global.h

int global_int = 1;

global1.cc

#include "global.h"

global2.cc

#include "global.h"int main()
{return 0;
}

使用以下命令,联合编译多个文件:

g++ global1.cc global2.cc -o main

结果编译报错:

/tmp/cc4Y38ub.o:(.data+0x0): global_int 的多重定义
/tmp/ccSwS0de.o:(.data+0x0):第一次在此定义
collect2: 错误:ld 返回 1

正确的做法是在头文件中使用extern声明,在源文件中定义。

global.h

extern int global_int;

globa1.cc

#include "global.h"int global_int = 1;

global2.cc

#include "global.h"
#include <iostream>extern int global_int;int main()
{std::cout << global_int << std::endl;return 0;
}

最后打印的结果为1.

更一般的做法是,在头文件声明外部变量,在对应的源文件初始化。此时在其他的源文件读取或者修改这个变量,达到跨文件全局变量的效果。在单线程场景下,这种做法十分有效。

以C语言的方式编译函数

在 C++ 里,为支持函数重载和类成员函数等特性,编译器会对函数名、类名等进行修饰,让它们在符号表中保持唯一。可以参考我写的这篇文章:【C++】filt工具的使用

比如刚才的代码:

#include <iostream>int get_int()
{return 1;
}int main()
{std::cout << get_int() << std::endl;return 0;
}

编译后对get_int提取名字:

0000000000400806 T _Z7get_intv

C语言是没有这个机制的,因为C语言不支持重载,当我们需要将代码打包为C接口供外部调用时,比如【Python】多线程/进程操作C++代码,就需要去掉这种修饰。

此时可以用extern "C"对函数调用进行包裹。编译器会按C语言的风格编译代码:

#include <iostream>extern "C"
{int get_int(){return 1;}
}int main()
{std::cout << get_int() << std::endl;return 0;
}

此时提取名字:

0000000000400806 T get_int

可以看到,名称修饰已经去掉了。

http://www.xdnf.cn/news/3442.html

相关文章:

  • Ubuntu20.04如何优雅的安装ROS 1(胎教级教程)
  • 【软件设计师:复习】上午题核心知识点总结(三)
  • 代码随想录单调栈part1
  • 前端面试每日三题 - Day 21
  • UN R79 关于车辆转向装置形式认证的统一规定(正文部分1)
  • 文章记单词 | 第59篇(六级)
  • SpringBoot 整合 RabbitMQ:Spring AMQP
  • 突破传统!TTRL如何开启大模型无监督强化学习新篇章?
  • B站Michale_ee——ESP32_IDF SDK——FreeRTOS_2 队列
  • NU1680低成本、无固件、高集成度无线充电电源接收器
  • 速通Ollama本地部署DeepSeek-r1
  • 【Redis】String详细介绍及其应用场景
  • Angular教程前言:历史、安装与用途
  • Git---GitHub Actions
  • 大模型 Function Call
  • 力扣面试150题--旋转链表
  • 编写教育网站后端页面笔记
  • 本地部署 n8n 中文版
  • 日期有关的算法题(ctime库的使用)
  • LLM与AI Agent交互范式的演进:从工具依赖到智能协同(深度解析)
  • Google NotebookLM正式支持中文!AI笔记助手开启中文创作新纪元
  • 常见电源的解释说明
  • 设计模式简述(十四)组合模式
  • 2.4流程控制语句
  • 笔试专题(十三)
  • 上位机知识篇---二进制操作
  • 【C到Java的深度跃迁:从指针到对象,从过程到生态】第五模块·生态征服篇 —— 第十九章 Spring生态:从main函数到企业级开发
  • 数字智慧方案5968丨智慧农业产销一体化云平台建设方案(72页PPT)(文末有下载方式)
  • 深入理解C语言中的整形提升与算术转换
  • 《Android 应用开发基础教程》——第十章:使用 Gson 实现网络 JSON 数据解析与对象映射