extern "c" 是解决c++与c混合编程中名字修饰导致链接失败的必要机制,需在头文件中用条件编译包裹声明,仅作用于函数和全局变量,且必须置于最外层作用域。

为什么 extern "C" 是绕不开的坎
因为 C++ 编译器会对函数名做名字修饰(name mangling),而 C 编译器不会。直接调用会导致链接失败,错误信息通常是 undefined reference to 'xxx' —— 即使函数声明、实现都写对了,链接器也找不到符号。
必须用 extern "C" 告诉 C++ 编译器:“这段声明/定义按 C 的规则处理,别改名字”。它不是语法糖,是 ABI 层面的契约。
- 只对函数声明和全局变量有效,类、模板、重载函数不能用
extern "C" - 在头文件中包裹 C 函数声明时,要加条件编译,否则 C 编译器会报错:
#ifdef __cplusplus extern "C" { #endif void c_func(int x); #ifdef __cplusplus } #endif - 如果 C 库头文件本身已带
extern "C"保护(比如<stdio.h></stdio.h>),你无需重复加;但自己写的 C 头文件,必须自己加
C++ 调用 C 函数时参数传递要注意什么
C 和 C++ 在基础类型上基本一致,但细节差异足以引发静默错误:比如 bool 在 C 中不存在(C99 才有 _Bool),char 的符号性(signed/unsigned)由平台决定,C++ 标准不强制规定。
- 避免直接传
std::string给 C 函数——C 看不到它的内存布局。用.c_str()或.data()转成const char*,并确保生命周期足够长 - 结构体传参优先用指针(
struct my_s*),而不是值传递。C++ 中结构体可能有隐式构造/析构,C 不理解;值传递还可能因填充字节(padding)导致大小不一致 - 回调函数注册时,C 接口要求函数指针是 C 链接的——你的回调函数本体也得用
extern "C"声明,否则注册进去的是一个 mangled 名字,C 代码调用时崩溃
链接 C 静态库(.a)或动态库(.so/.dll)常见报错
即使 extern "C" 写对了,链接阶段仍可能失败,典型错误是 undefined reference 或 cannot find -lxxx。
Shell本身是一个用C语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Linux系统
立即学习“C++免费学习笔记(深入)”;
-
g++ main.cpp -lmyc -o app报cannot find -lmyc:说明链接器没找到库文件。确认libmyc.a或libmyc.so在标准路径(如/usr/lib)或显式指定路径(-L/path/to/lib) - 库存在但符号仍找不到:用
nm -C libmyc.a | grep c_func(Linux/macOS)检查符号是否真的以 C 链接方式导出(应显示为T c_func,而非T _Z7c_funci) - Windows 下用 MinGW 编译 C++ 程序链接 MSVC 编译的 C DLL?不行。ABI 不兼容:调用约定(
__cdeclvs__stdcall)、运行时(msvcrt.dll vs libstdc++)全都不匹配。必须用同一套工具链
头文件里 extern "C" 放错位置会怎样
放在函数定义体内、或者放在 namespace 里,都会失效。C++ 标准规定 extern "C" 只能作用于“声明”,且必须在最外层作用域。
- 错误写法:
void foo() { extern "C" void c_func(); }→ 编译器忽略,不报错但无效果 - 错误写法:
namespace ns { extern "C" void c_func(); }→ 符号变成ns::c_func,仍是 C++ 链接,C 代码无法调用 - 正确写法:头文件顶部加条件宏包裹,或在 C++ 源文件里单独声明:
extern "C" { void c_func(int); }(仅限该文件内使用)
最容易被忽略的是:C 头文件被多个 C++ 文件包含时,每个包含点都必须满足 extern "C" 环境。漏掉一个,就可能链接失败,而且错误位置和实际问题位置不一致。








