在C++中调用C函数需使用extern "C"解决名字修饰问题。C++编译器会对函数名进行name mangling以支持重载,而C语言不会,导致链接时符号不匹配。通过在头文件中用extern "C"包裹函数声明,并结合#ifdef __cplusplus条件编译,可确保C++正确识别C函数符号。例如,在math_utils.h中声明add函数时使用extern "C",C++程序main.cpp包含该头文件后即可调用add函数。编译时先分别用gcc和g++编译C和C++文件为目标文件,再用g++链接,或直接用g++一次性完成。对于多个C函数,可将所有声明置于extern "C"块内。注意extern "C"不支持C++重载,且仅影响链接方式不影响调用约定;若C++函数需被C调用,也须用extern "C"声明并避免类成员函数。正确使用extern "C"和条件编译可实现C与C++的可靠互操作,广泛应用于混合编程场景。

在C++中调用C语言的函数,关键在于解决C++编译器对函数名的名字修饰(name mangling)问题。C++支持函数重载,因此编译器会将函数名、参数类型等信息编码成唯一的符号名,而C语言不支持重载,函数名不会被修饰。如果直接调用C函数,链接时可能出现“undefined reference”错误。
使用 extern "C" 声明C函数
为了让C++正确识别C语言编译生成的函数符号,需要用 extern "C" 包裹C函数的声明。这会告诉C++编译器:这部分函数遵循C语言的链接规则,不要进行名字修饰。
示例:调用一个C语言实现的加法函数
假设有一个C语言源文件 math_utils.c:
include "math_utils.h"
int add(int a, int b) {
return a + b;
}
对应的头文件 math_utils.h:
ifndef MATH_UTILS_H
define MATH_UTILS_H
立即学习“C语言免费学习笔记(深入)”;
ifdef __cplusplus
extern "C" {
endif
int add(int a, int b);
ifdef __cplusplus
}
endif
立即学习“C语言免费学习笔记(深入)”;
endif
上面的条件编译判断是否在C++环境中,如果是,则用 extern "C" 包裹函数声明,避免C++名字修饰;C编译器会忽略这个语法。
现在在C++文件中调用它,比如 main.cpp:
include iostream>
include "math_utils.h"
int main() {
std::cout
return 0;
}
编译与链接方法
需要分别编译C和C++源文件,然后链接成可执行程序。常用命令如下:
gcc -c math_utils.c -o math_utils.o # 编译C文件
g++ -c main.cpp -o main.o # 编译C++文件
g++ main.o math_utils.o -o app # 链接所有目标文件
也可以一步完成:
g++ main.cpp math_utils.c -o app注意:虽然g++可以编译C代码,但确保C代码用C编译器逻辑处理,尤其是涉及标准库或复杂宏时。
多个C函数或整个C库的调用
如果要调用多个C函数,可以把所有声明都放在 extern "C" 块中:
ifdef __cplusplus
extern "C" {
endif
void func1(int x);
int func2(const char* str);
float func3(float a, float b);
ifdef __cplusplus
}
endif
这样C++代码就可以安全调用这些C函数,链接时不会因符号名不匹配而失败。
常见问题与注意事项
- C++不能用 extern "C" 声明重载函数,因为C不支持重载
- extern "C" 只影响链接方式,不影响调用约定(如__stdcall等需额外指定)
- 若C++函数要被C代码调用,该C++函数也必须用 extern "C" 声明,并且不能是类成员函数或重载函数
- 确保头文件被C和C++共同包含时行为一致,使用 #ifdef __cplusplus 是标准做法
基本上就这些。只要正确使用 extern "C" 和条件编译,C++调用C函数非常稳定可靠,广泛应用于系统编程、嵌入式开发和混合项目中。











