extern "C" {} 在C++编程中的作用

发布时间 2023-05-24 09:54:10作者: 严_青
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
}

这里的extern "C"的作用是指定头文件使用的编译器吗?

extern "C"的作用不是指定头文件使用的编译器,而是确保在C++代码中包含的这些C语言头文件使用C语言的调用约定和名称规范。因为C++支持函数重载,其名称规范(name mangling)会将函数名、参数类型等信息编码到符号名中。而C语言没有这种名称规范。

当在C++代码中混合使用C语言库时,使用extern "C"告诉编译器在处理这些头文件时,采用C语言的调用约定和名称规范。这样可以确保C++编译器不会对C语言库中的函数和变量名进行名称修饰(name mangling),从而避免链接错误。

例如,在C++代码中使用FFmpeg这样的C语言库时,在包含头文件前添加extern "C"

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
}

这样做可以确保与FFmpeg库正确链接,并能够调用库中的函数。

对C语言库中的函数和变量名进行名称修饰(name mangling) 具体是什么?

名称修饰(name mangling)是一种编译器技术,用于在生成目标代码时对函数和变量名进行编码。这种技术主要用于解决两个问题:函数重载(function overloading)和C++的命名空间(namespaces)。C++编译器通过名称修饰来区分具有相同名称但参数类型或命名空间不同的函数。

名称修饰将函数名、参数类型、命名空间等信息结合起来,生成一个独特的符号名。这样即使两个函数在源代码中具有相同的名字,名称修饰后的符号名也会不同,从而消除歧义。例如,在C++代码中:

namespace test {
    int func(int a, float b) {
        return static_cast<int>(a * b);
    }
    double func(double a, double b) {
        return a * b;
    }
}

经过名称修饰后,这两个func函数可能生成如下符号名(以GNU g++编译器为例):

_ZN4test4funcEif
_ZN4test4funcEdd

由于C语言不支持函数重载和命名空间,因此C编译器不需要名称修饰。当在C++代码中使用C语言库时,需要告诉C++编译器使用C语言的调用约定和名称规范,以避免链接错误。extern "C"就是用来实现这一目的的。

在包含C语言头文件时使用extern "C",可以确保C++编译器不会对C语言库中的函数和变量名进行名称修饰,从而正确链接库并调用其中的函数。