开门见山

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

再按上述过程编译,则程序可以编译通过,正确运行。效果见下图。

说点什么
请文明发言!
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...