extern “C“ in C++
English:extern Ctells the C compiler to use C linkage for a declaration or definition, which mainly disables C name mangling.中文extern C告诉 C 编译器这个声明或定义要使用C 链接方式最主要的效果就是关闭 C 的名字重整。English:It does not mean “compile this file as C”. It only changes symbol linkage.中文它并不表示“把这个文件按 C 来编译”它只是改变符号链接方式。实验 1.c和.cpp都用g编译.c .cpp both compile with gmain.cpp#include iostream #include test.h // extern C void show(); void test01() { show(); } int main() { test01(); return EXIT_SUCCESS; }test.h#include stdio.h void show();test.c#include test.h void show() { printf(hello world.\n); }both get C linkageg main.cpp test.c -o mainshaoyoulushaoyoulu:~/Code/extern$ g main.cpp test.c -o main shaoyoulushaoyoulu:~/Code/extern$ ./main hello world.English:When you rung main.cpp test.c -o main, both files are compiled as C translation units. The.csuffix does not force C mode when the compiler isg.中文当你执行g main.cpp test.c -o main时这两个文件都会被当成C 翻译单元编译。.c后缀并不会强制让g进入 C 模式。English:That is why the program works even withoutextern C: both declaration and definition are C linkage, so they match.中文这就是为什么即使没有extern C程序也能运行因为声明和定义都被当成 C 链接方式所以符号是匹配的。English:This experiment proves only one thing:gcompiles.cfiles as C when you askgto compile them.中文这个实验只证明了一件事当你让g去编译时它会把.c文件也按 C 处理。实验 2main.cpp用gtest.c用gcc但没有extern C.cpp compile with g, .c compile with gccwithoutextern C void show();shaoyoulushaoyoulu:~/Code/extern$ g -c main.cpp -o main.o shaoyoulushaoyoulu:~/Code/extern$ gcc -c test.c -o test.o shaoyoulushaoyoulu:~/Code/extern$ g main.o test.o -o main /usr/bin/ld: main.o: in function test01(): main.cpp:(.text0x9): undefined reference to show() collect2: error: ld returned 1 exit status shaoyoulushaoyoulu:~/Code/extern$undefined reference to show()English:This is the real mixed C/C test.gcccompilestest.cas C, soshowhas C linkage.gcompilesmain.cppas C, soshow()in the declaration has C linkage by default.中文这才是真正的 C/C 混合测试。gcc把test.c按 C 编译所以show是 C 链接g把main.cpp按 C 编译所以show()的声明默认是 C 链接。English:The linker then sees two different symbols: one unmangled C symbol and one mangled C symbol. So it reportsundefined reference to show().中文于是链接器看到的是两个不同的符号一个是未重整的 C 符号一个是 C 重整后的符号所以报undefined reference to show()。实验 3在main.cpp中加上extern C void show();withextern C void show();main.cpp#include iostream //#include test.h extern C void show(); void test01() { show(); } int main() { test01(); return EXIT_SUCCESS; }shaoyoulushaoyoulu:~/Code/extern$ g -c main.cpp -o main.o shaoyoulushaoyoulu:~/Code/extern$ gcc -c test.c -o test.o shaoyoulushaoyoulu:~/Code/extern$ g main.o test.o -o main shaoyoulushaoyoulu:~/Code/part1/extern$ ./main hello world. shaoyoulushaoyoulu:~/Code/extern$English:Now the C compiler is told to treatshowas a C-linked symbol. It no longer mangles the name, so the declaration matches the C definition compiled bygcc.中文这时 C 编译器被告知show是 C 链接符号不要重整名字。于是这个声明就能和gcc编译出来的 C 定义匹配上。English:That is why the program links and runs correctly.中文这就是为什么程序能正确链接并运行。important concepts to emphasize1extern C的本质English:extern Cis a linkage specification, not a storage class and not a compiler switch.中文extern C是一种链接说明不是存储类别也不是编译器开关。English:Its main purpose is to make C±compiled code produce C-compatible symbols.中文它的主要目的是让 C 编译出来的代码生成C 兼容的符号名。2 C 为什么需要它English:C supports function overloading, namespaces, and more advanced type information, so it encodes extra information into symbol names. This is name mangling.中文C 支持函数重载、命名空间以及更复杂的类型信息所以它会把额外信息编码进符号名这就是名字重整。English:C does not need that, so C symbols are simple and unmangled.中文C 不需要这些机制所以 C 的符号名通常是简单直接的、不会重整。3extern C不能做什么English:extern Cdoes not magically make C code legal in a C file. It only changes linkage.中文extern C不会让 C 代码在 C 文件里“自动合法”它只改变链接方式。English:It also does not make two different function signatures compatible. The parameter types and return type still must match.中文它也不会让两个不同函数签名变成兼容。参数类型和返回值类型仍然必须匹配。extern C标准写法头文件写法 / Header patterntest.h#ifdef __cplusplus extern C{ #endif #include stdio.h void show(); #ifdef __cplusplus } #endifEnglish:This is the standard mixed C/C header pattern.中文这是标准的 C/C 混合头文件写法。English:If the header is included by C code,showgets C linkage. If it is included by C code, theextern Cpart is ignored because__cplusplusis not defined.中文如果这个头文件被 C 代码包含show就会获得 C 链接如果被 C 代码包含因为__cplusplus没定义extern C那部分就会被跳过。main.cpp#include iostream #include test.h void test01() { show(); } int main() { test01(); return EXIT_SUCCESS; }test.c#include test.h void show() { printf(hello world.\n); }shaoyoulushaoyoulu:~/Code/extern$ g -c main.cpp -o main.o shaoyoulushaoyoulu:~/Code/extern$ gcc -c test.c -o test.o shaoyoulushaoyoulu:~/Code/extern$ g main.o test.o -o main shaoyoulushaoyoulu:~/Code/part1/extern$ ./main hello world. shaoyoulushaoyoulu:~/Code/extern$extern C出现在声明端还是定义端English:In mixed-language projects, the most common practice is to putextern Cin the header declaration, so both C and C translation units stay consistent.中文在混合语言工程中最常见的做法是把extern C放在头文件声明处这样 C 和 C 的翻译单元都能保持一致。English:If both declaration and definition are compiled as C, then both sides must agree on C linkage if you want a C symbol.中文如果声明和定义都按 C 编译那么两边都必须约定使用 C 链接否则不会得到 C 符号。extern C和重载English:Functions declared withextern Ccannot be overloaded, because C linkage does not carry type information for overload resolution.中文被声明为extern C的函数不能重载因为 C 链接不携带用于重载解析的类型信息。English:This is another important reason whyextern Cis only for interface boundaries.中文这也是为什么extern C主要用于接口边界而不是随便在内部代码里乱用。纯 C不需要extern CEnglish:Show that compiling everything withgmakes the program work because everything is C.中文先展示“全部用g编译”时程序能工作因为整个程序都被当成 C。真正的 C C 混编必须用extern CEnglish:Then showg main.cppgcc test.c, and let it fail withoutextern C.中文然后展示g main.cppgcc test.c在没有extern C时失败。加上extern C后成功English:Finally, add theextern Cguard in the header or declaration, and show the link succeeds.中文最后加上头文件里的extern C保护展示链接成功。MisconceptionsEnglish:Misconception 1:.cfiles are always compiled as C.中文误区 1.c文件总是按 C 编译。English:Correction: the compiler determines the language mode.gwill compile.cfiles as C.中文更正语言模式由编译器决定。g会把.c文件按 C 编译。English:Misconception 2:extern Cchanges runtime calling behavior.中文误区 2extern C会改变运行时调用行为。English:Correction: it mainly changes symbol linkage and mangling, not the high-level function logic.中文更正它主要改变的是符号链接和名字重整不改变函数逻辑本身。English:Misconception 3: Onceextern Cis added, any C and C code can freely mix.中文误区 3加了extern C后C 和 C 就能随便混用。English:Correction: types, headers, memory management, and API conventions still must be compatible.中文更正类型、头文件、内存管理、API 约定仍然必须兼容。