==== 《知其然篇》 ====
在分析各種源碼庫時,經常會遇到extern “C”好奇了好久,也沒去深入研究一下他到底有什么作用?為什么要加呢?先來看一下extern "C"出現的樣子。
=================================extern "C"的作用=================================
其實這個用法在頭文件中用的比較多,也就是我們所說的.h文件,那么為什么要在頭文件中加入這個玩意兒呢。
解釋:因為頭文件在編譯器的預處理階段會被包含進相應的源文件中,而源文件會有兩種不同的編譯規則,C語言規則和C++語言規則,于是乎,就會出現一個#ifdef __cplusplus的宏,用來盤問一下,這個代碼內嵌的源碼到底是以什么規則進行編譯的?
我們大概知曉了,extern "C"是用來限制編譯的編譯規則的,而且是文件內局部進行限定的,他并不是要將源文件一網打盡,因為C和C++這對好兄弟一般都不是分家的。
==== 來盤一下GCC編譯器 ====
上面我們了解到C和C++雖然是一對不分家的兄弟,但是他們的性格(編譯規則)是完全不同的,所以如果你不清晰的告訴GCC編譯器,它可能也很難完全分清這對兄弟。
GCC編譯器集成了C和C++兩種語言的編譯規則,那什么時候用那種規則進行編譯呢?
xxx.c:默認以編譯 C 語言程序的方式編譯此文件。
xxx.cpp:默認以編譯 C++ 程序的方式編譯此文件。
這么來看不是挺清楚的嗎?為啥還需要用extern c 來指定某一段代碼用c格式來編譯?
首先你要明白一點,.h文件最終是要被包含進行源文件中進行編譯的,源文件可能是.c文件,也可能是.cpp文件。
其次,你要明白.h文件的作用是什么,他僅僅是個接口文件,源文件的調用接口,實際提供功能的還是某個特定的源文件,你無法通過.h文件本身知曉其對應用源文件是c文件還是cpp文件。
.h文件通常會被以#include的形式包含到某個特定的源文件,那么尷尬的事情就發生了。
==== C/C++編譯規則的差異,舉個例子 ====
假如:一個.cpp文件調用了一個接口.h的文件想要調用其API,這時候會有兩種情況,假如.h文件的API對應在.cpp文件中,那么不會有任何問題,但如果這個API函數是由.c文件提供的支持,那就尷尬了,因為編譯器處理完之后,會發現同一個函數,其名字不一致,從而導致編譯器無法進行有效的連接,而給你一個大大的ERROR.
==== C/C++為什么要做成混合編程? ====
C和C++通常是可以混合編程的,因為在long long ago 之前,那時候是C語言的天下,很多的庫都是以C的規則編寫的,后來有了C++,曾也有人想過,要把C規則的庫全部用C++重寫一遍,但是工作量之大,這個想法根本不現實。于是乎,C++就得兼容著那些C庫去用,于是乎就不得不兼容C,于是有了extern "C"來協調他們的關系。