在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”声明?

一、先搞懂核心问题:C 和 C++ 的 "函数名编译差异"

C++ 支持函数重载 (比如func(int)func(float)可以共存),为了区分不同重载的函数,C++ 编译器会对函数名做「名字修饰(Name Mangling)」------ 把函数的参数类型、个数等信息拼接到函数名里,生成一个独一无二的编译后名字。而 C 语言不支持重载,C 编译器对函数名的处理非常简单:基本直接保留原函数名(或仅做简单修饰)。

举个直观例子:

定义一个简单函数 void func(int);

  • C 编译器编译后 :函数名还是func(或类似_func的简单形式);
  • C++ 编译器编译后 :会变成_Z4funci(不同编译器格式略有差异,核心是拼接了参数类型int的标识)。

二、不加 extern "C" 会发生什么?

假设你有一个用 C 编译器编译的函数库,里面有void func(int);,编译后函数名是func;当你在 C++ 代码里直接调用func(10);时:

  1. C++ 编译器会按自己的规则,把代码里的func解析成修饰后的名字(比如_Z4funci);
  2. 链接阶段,编译器会去找_Z4funci这个函数,但 C 编译的库中只有func,找不到对应符号,最终报链接错误(undefined reference to func(int)

三、extern "C" 的作用:告诉 C++ 编译器 "按 C 规则处理"

extern "C"是 C++ 的特有语法,它的核心作用是:让 C++ 编译器对被修饰的函数,按 C 语言的规则处理(包括名字修饰、调用约定等)

正确的使用方式(示例):
cpp 复制代码
// 1. 声明C编译的函数(告诉C++按C规则找这个函数)
extern "C" {
    void func(int); // 这个函数是C编译器编译的
}

// 2. 调用函数(C++编译器会按C的名字"func"去链接)
int main() {
    func(10); 
    return 0;
}

如果是批量引入 C 的头文件,更常用的写法(兼顾 C/C++ 编译):

cpp 复制代码
// 假设这是C的头文件 func.h
#ifdef __cplusplus // 识别C++编译器
extern "C" {
#endif

void func(int); // C风格函数声明

#ifdef __cplusplus
}
#endif

四、补充:为什么 C 不需要处理 C++ 的函数?

因为 C 语言不支持extern "C"语法,也不会去调用 C++ 的重载函数 ------ 通常都是 C++ 调用 C 的代码(比如老的 C 语言库),所以只需要在 C++ 侧做声明即可。

总结

  1. 核心原因 :C++ 的「名字修饰」和 C 不同,不加extern "C"会导致链接时找不到 C 编译的函数;
  2. extern "C" 的作用:强制 C++ 编译器对目标函数采用 C 的名字修饰规则,匹配 C 编译的函数符号;
  3. 使用场景:C++ 调用 C 语言编写 / 编译的函数、库(如 C 标准库、第三方 C 库)时必须加。

简单记:extern "C"就是 C++ 和 C 之间的 "翻译官",让两者能正确识别对方编译的函数。

相关推荐
玖玥拾25 分钟前
C/C++ 基础笔记(十三)继承
c语言·c++·继承
z落落36 分钟前
C#WinForm 窗体切换与窗体传值(登录跳转案例)+WinForm 窗体传值(从上往下传、从下往上传)
开发语言·windows·c#
Dontla1 小时前
git bash打开Claude code报错:Claude Code on Windows requires git-bash.(别把git装其他位置,严格按照默认安装)找不到claude code
windows·git·bash
一个梦醒了1 小时前
安装git bash选项推荐
开发语言·git·bash
ao-weilai2 小时前
C++:哈希表
c++·哈希算法·散列表
汉克老师2 小时前
GESP7级C++考试语法知识(二、指数函数(1、pow() 函数)
c++·指数函数·pow·gesp7级·精度误差
comcoo2 小时前
电脑自动干活不用值守!OpenClaw 本地部署完整实操流程
windows·开源·github·open claw部署·open claw部署包
旖-旎2 小时前
FloodFill(图像渲染)(1)
c++·算法·深度优先·力扣
蓝鸟19743 小时前
Windows Route 内外网双通原理+实战详解(彻底解决双网卡互斥断网)
windows·网络运维·电脑网络配置·路由冲突解决·route命令·内外网同时上网·windows路由 双网卡双通
汉克老师3 小时前
GESP2026年3月认证C++六级真题与解析(编程题1 选数)
c++·动态规划·线性dp·gesp六级·状态转移·选与不选