- #ifdef __cplusplus
- extern "C" {
- #endif
- …… (C函數聲明)
- #ifdef __cplusplus
- }
- #endif
簡單來說,這個extern“C”用於C++代碼調用C的函數(至於C代碼如何調用C++函數,還是問問Google大神吧~)
先撇開上述的extern “C”,看看C函數和C++函數的彙編代碼,就知道在目標文件中,C函數名和C++函數名採用不同的命名規則。
VS2010新建一個Windows Console工程,添加一個.c和.cpp文件,文件裏的代碼都一樣,如下
- void hello()
- {
- }
爲了使彙編文件的內容簡單一些,這裏函數體是空,而且沒有引入任何頭文件。VS2010默認不輸出.asm文件,即彙編文件。在工程的配置中,讓VS2010輸出彙編文件,如下
編譯解決方案(或按“F7”),可以在工程目錄的Debug文件夾下,找到對應的兩個彙編文件,內容如下
沒有必要把這裏全部的彙編代碼看懂,只要明白在源代碼中同一個hello函數,在翻譯過來的.asm文件中,hello函數名的命名不一樣就行了。
很明顯,如果C++代碼要調用C函數,需要按照C函數編譯後的函數名去調用這個函數。所以,extern “C”的作用就是告訴編譯器,花括號“{}”中間的這些函數聲明全部都是C函數。
下面修改一下.c和.cpp文件的內容,如下
- // C代碼
- #include <stdio.h>
- void hello()
- {
- printf("Hello, world!\n");
- }
- // C++代碼
- void hello();
- int main(void)
- {
- hello();
- }
這裏要說明下,由於.c和.cpp文件在同一個工程下,所以簡單起見,沒有使用頭文件引入hello函數,這裏hello函數是全局的。運行工程發現出錯如下
這裏?hello@@YAXXZ就是上面.cpp文件中hello函數編譯後出現在對應的.asm文件中的。顯然,編譯器按照這個名稱去找目標文件(.obj文件)中的hello是找不到的,因爲.c文件編譯後的.obj文件中,hello函數名被改成_hello。
這時,把extern “C”加到.cpp文件中,如下
- extern "C" {
- void hello();
- };
- int main(void)
- {
- hello();
- }
果然,程序可以通過編譯運行了。到這裏,基本上extern ”C”的作用都講清楚了。至於__cplusplus宏,用於判斷當前源文件是不是C++源文件,因爲extern “C”這種寫法在C源文件中不允許的,如下,所以使用__cplusplus宏可以避免extern “C”被引入到C源文件中。即
(1)當前源文件是C++,則__cplusplus宏生效,extern “C”以及花括號“{}”的內容被引入C++源代碼中;
(2)當前源文件是C,則__cplusplus宏無效,extern “C”以及花括號“{}”的內容不被引入C源代碼中。