开门见山
extern "C"是C++特有的指令(C无法使用该指令),常用于支持C++/C混合编程,其作用是告诉C++编译器用C规则编译指定的代码(除函数重载外,extern "C"不影响C++其他特性)。
原理分析
函数重载
C不支持函数重载,C++支持函数重载,可以根据参数类型来区别同名函数。
//test.cpp
#include <cstdio>
void print(char c)
{
printf("This is a char : %c\n", c);
}
void print(int a)
{
printf("This is an int : %d\n", a);
}
int main()
{
int a = 3;
char c = '7';
print(a);
print(c);
return 0;
}
由上述代码,可以看到名为print的函数定义了两个,但是传入的参数类型不同。使用g++编译代码,运行,可以得到如下图所示输出:

可以看到,程序可以编译通过并正常执行。
使用g++对test.cpp进行汇编编译,得到test.s文件。
g++ -S test.cpp
打开test.s文件,可以看到,两个print函数经过编译,在汇编文件中形成的函数符号是不同的。一个是_Z5printc,一个是_Z5printi,函数符号后的c和i就是参数类型的代表,c表示char,i表示int。这个函数符号是后面程序进行链接时需要使用的。C++也是基于此,可以实现根据不同类型参数区分同名函数的。

函数符号
//myAdd.c
#include <stdio.h>
void myAdd(int a, int b)
{
int c = a + b;
printf("%d\n", c);
return;
}
C和C++生成函数符号的规则是不同的。使用g++和gcc分别生成myAdd.c的汇编文件,可以得到如下图所示结果,其中myAdd函数按C++规则生成的函数符号是_Z5myAddii,而按C规则生成的函数符号是myAdd。


如果C和C++混合编程,myAdd.c使用C编译器,某CPP文件使用C++编译器编译,其中引用了myAdd函数,而又没有使用extern "C",就会报myAdd函数未定义的错误。具体过程如下图所示。

main.cpp和myAdd.h代码见下。
//main.cpp
#include <cstdio>
#include "myAdd.h"
int main()
{
int a, b;
scanf("%d%d", &a, &b);
myAdd(a, b);
return 0;
}
//myAdd.h
void myAdd(int a, int b);
而当加入extern "C"后,即把main.cpp改成如下所示,其中__cplusplus是C++标准库中预先定义的宏。
#ifdef __cplusplus
extern "C" {
#endif
#include <cstdio>
#include "myAdd.h"
int main()
{
int a, b;
scanf("%d%d", &a, &b);
myAdd(a, b);
return 0;
}
#ifdef __cplusplus
}
#endif
再按上述过程编译,则程序可以编译通过,正确运行。效果见下图。

声明:
本文采用
BY-NC-SA
协议进行授权,如无注明均为原创,转载请注明转自
SigmaPoet
本文地址: extern “C”浅析
本文地址: extern “C”浅析