【C++】009、extern关键字

一、extern关键字设计的目的只有一个:那就是跨文件、跨语言地正确找到符号

  • 作为外部声明,告诉编译器变量或函数在别的文件里有定义,让编译器去别的目标文件找查看,先别急着报错。

  • 配合C语言使用(extern "C"),用于禁止C++的符号修饰(Name Mangling)功能,实现C和C++的混合编程

二、extern的基础使用

修饰变量或函数,只做声明,不定义

  • 本质:extern 关键字修饰的声明是承诺,而不是定义,它不分配内存,只是告诉编译器,这个符号(变量/函数)在其他编译单元(.cpp文件)中有定义,请链接时去哪里找。

  • 代码实现

cpp 复制代码
// FileA.cpp
int g_counter = 0;          // 定义(分配内存)
void logMessage() { ... }   // 定义

// FileB.cpp
extern int g_counter;       // 声明(不分配内存),告诉编译器去外部找
extern void logMessage();   // 声明(通常省略,函数默认就是extern的)

void test() {
    g_counter++;            // 链接时去 FileA.obj 找 g_counter
    logMessage();           // 链接时去 FileA.obj 找 logMessage
}

三、extern "C"的底层原理与使用场景

1、为什么需要设计出extern "C"?

  • 一句话总结:为了让C++兼容C,实现在C++程序中调用C语言函数库

  • C语言:符号名就是函数名,比如 void foo(int) 他的符号名就是 foo (注意C语言没有函数重载)

  • C++:支持函数重载,编译器会进行名字修饰,void foo(int) 会被修饰为 _Z3fooi, 在修饰后的符号名会标记参数信息

使用冲突:

  • 如果C++程序要调用一个C语言的库(.so, .a),默认链接时会去找 _Z3fooi,但C语言的库中只有foo,肯定找不到,会报链接错误(Undefined Reference)

2、extern "C"的标准写法

1)直接包裹单个函数

  • 在C++程序中调用C语言函数
cpp 复制代码
extern "C" {
    void c_function(int x);   // 告诉编译器:按 C 的规则去找这个函数
    int c_global_var;
}

2)兼容C/C++两种语言的双编译的头文件中调用extern

  • 既能让C++编译器识别,也能让C编译器识别

  • __cplusplus是C++编译器内置的宏

cpp 复制代码
// my_module.h
#ifdef __cplusplus
extern "C" {
#endif

// 这里是 C 语言接口声明(结构体、函数原型)
void init_module();
void process_data(int* data, int len);

#ifdef __cplusplus
}
#endif

3、类成员不能使用extern "C"

  • extern "C"只能修饰全局函数和全局变量

  • 不能作用域类成员函数,因为成员函数this指针和虚表(vtable),而C语言没有这两个概念

相关推荐
麦麦麦当劳大王1 小时前
【油猴脚本】Boss直聘 岗位职责复制
开发语言·前端·javascript
starzy19901 小时前
深入理解Scala Map:从实现原理到工程实践
开发语言·后端·scala
只睡四小时2 小时前
Three.js Sub-tick:漏判 60.7%→0
开发语言·javascript·性能优化·ecmascript·游戏开发·three.js·碰撞检测
码农小河662 小时前
基于SSM+JSP的高校专业信息管理系统【附源码+数据库】
java·开发语言·数据库
东鹏特饮4 小时前
系统运维(传统/通用运维)面试题
开发语言·php
风若飞5 小时前
Spring Ai 入门遇到问题1
java·后端·spring
今天要早睡_5 小时前
C++01_入门基础复习
开发语言·c++
Nuanyt5 小时前
LeetCode Hot 100 链表专题(五)· 2 题(Java)
java·算法·leetcode·链表
黑马程序员毕设6 小时前
基于 Java 的餐饮点餐系统设计与应用报告
java·开发语言
SL_staff6 小时前
从文档工具到知识中枢:基于JVS数字底座构建企业级统一内容管理平台的技术实践
java·开源·全栈