<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

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

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    正好是我們代碼中遇到的問題,之前不求甚解,只用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++中使用這個庫文件,我們需要這樣寫:

      1 2 3 4 ; html-script: false ]extern &quot;C&quot; { #include &quot;f.h&quot; }

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

      1 2 3 4 5 6 7 8 9 ; html-script: false ]#ifdef __cplusplus extern &quot;C&quot; { #endif   //一段代碼   #ifdef __cplusplus } #endif

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

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

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

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全