extern “C”的含义

extern "C" 完整讲解(C++ 专用,解决 C/C++ 混编符号兼容)

1. 核心作用

C++ 支持函数重载、命名空间、类成员函数 ,编译时会对函数名做名字改编(Name Mangling) ; C 语言没有重载,不会修改函数名。 extern "C" 的作用:告诉 C++ 编译器,这段代码按照 C 语言规则编译、生成 C 风格符号,不做名字改编

2. 两种使用场景

场景 1:C++ 调用 C 写的库(最常用)

C 库头文件(比如 stdio.h、自定义 C 静态库)直接在 C++ 里引入会链接报错,因为符号名对不上。

标准写法(头文件兼容 C/C++):

cpp 复制代码
#ifdef __cplusplus
extern "C" {
#endif

// C 风格函数声明
void func(int a);
int add(int x, int y);

#ifdef __cplusplus
}
#endif

含义:

  • 如果是 C++ 编译器编译,包裹在 extern "C" {} 内,函数按 C 规则导出符号;
  • 如果是 C 编译器,__cplusplus 未定义,直接忽略这段标记。

场景 2:C 调用 C++ 写的函数

C 不能识别 C++ 改编后的函数名,C++ 对外暴露接口必须加 extern "C"

cpp 复制代码
// .cpp 文件
extern "C" void cpp_api()
{
    // 内部可以正常写C++代码:类、string、重载等
}

编译后 cpp_api 符号名不变,C 代码可以直接 void cpp_api(); 调用。

3. 对比有无 extern "C" 的符号差异

举个例子:void test(int)

  1. 不加 extern "C"(纯 C++) GCC 改编后符号:_Z4testi
  2. 加 extern "C" 符号直接为:test

链接器去库中找符号时名字必须完全匹配,名字不一致就报 undefined reference

4. 关键限制

  1. extern "C" 内部不能写 C++ 重载函数 C 不支持重载,多个同名 C 函数会符号冲突:

    cpp 复制代码
    extern "C" {
        void f(int);
        void f(double); // 编译报错,C不允许重载
    }
  2. 只能修饰全局普通函数 / 全局变量,不能修饰类、成员函数、模板。

  3. extern "C" 只影响编译阶段符号生成,函数内部逻辑依然可以完整使用 C++ 特性(类、STL、异常等)。