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

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語言庫中的函數和變量名進行名稱修飾,從而正確鏈接庫並調用其中的函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章