gcc,g++,extern “C” :一些編譯錯誤的緣由


正好是我們代碼中遇到的問題,之前不求甚解,只用g++編譯沒有錯誤就不管了,現在要跨平台到windows下就遇到了問題。
全文轉載自:http://user.qzone.qq.com/75172588/blog/1248167335

gcc和g++的區別
1、gcc
在編譯階段,把后綴為.c的源文件按照c語法和方式進行編譯;把后綴為.cpp的源文件,按照c++語法和方式進行編譯。
在鏈接階段,不自動和C++程序使用的庫鏈接。所以,.cpp如果有c++的代碼,可能會產生鏈接錯誤;.c不存在這個問題,因為如果.c如果有c++的代碼,編譯時就會不通過。
2、g++
在編譯階段,無論是.c還是.cpp,都按照c++的語法和方式進行編譯。其實,g++是調用gcc進行編譯。
在鏈接階段,會自動和C++程序使用的庫鏈接,即便是純c程序,也會鏈接這些庫。

為什么需要extern “C”?
在c++中,為了支持重載機制,在編譯生成的匯編碼中,要對函數的名字進行一些處理,加入比如函數的返回類型等等。而在C中,只是簡單的函數名字而已,不會加入其他的信息。也就是說,C++和C對產生的函數名字的處理是不一樣的。所以,在gcc和g++下編譯,會有如下效果:
gcc編譯.c文件,因為是按照c方式編譯,所以函數名不變;
gcc編譯.cpp文件,g++編譯.c文件,g++編譯.cpp文件,因為是按照c++方式編譯,所以函數名加上了附加信息。

在被編譯的c++程序中,如果調用了其他的庫的函數,則這個函數名也是照加了附加信息的函數名來調的,這樣,如果這個庫是c方式編譯的,那么在庫中的函數名是不帶附加信息的,這樣的調用鏈接就會失敗,因為函數名不對應導致找不到。

在這樣的場景下,就需要引入extern “C”。
extern “C”是告訴編譯器:這是一個用C寫成的庫文件,請用C的方式來鏈接它們。
一般的用法是,比如,現在我們有了一個C庫文件,它的頭文件是f.h,產生的lib文件是f.lib,那么我們如果要在C++中使用這個庫文件,我們需要這樣寫:

另外,被調函數的實現如果包在extern “C”中,意味着強制按c方式來編譯,具體如下:
gcc編譯.c文件,會編譯不通過,因為c語法中沒有extern “C”,實際上在這種情況下根本不需要把函數實現包在extern “C”中,因為這種情況下本來就是按c方式來編譯的。因此通常會把代碼寫成這樣:

__cplusplus宏標志着編譯器將會把代碼按C還是C++語法來解釋,如上所述,如果后綴為.c,並且采用gcc編譯器,則該宏就是未定義的,否則,就是已定義的。
gcc編譯.cpp文件,g++編譯.c文件,g++編譯.cpp文件,函數名不變,即采用c的方式。

為什么要把被調函數的實現包在extern “C”里呢?我想是為了使c程序也能調用它,否則就沒有什么必要了。

后記:cl編譯器的規則與gcc相同。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM