extern “C”的簡單解析

來源:互聯網
上載者:User

1.揭密extern "C"

extern "C"包含雙重含義,從字面上即可得到:首先,被它修飾的目標是 "extern”的;其次,被它修飾的目標是 "C”的。
首先來看一下 "extern”的含義
a.在一個檔案內,如果外部變數不在檔案的開頭定義,其有效範圍只限定在定義到檔案的結束處。如果在定義前需要引用該變數,則要在引用之前用關鍵字 "extern” 對該變數做“外部變數聲明”,表示該變數是一個已經定義的外部變數。有個這個聲明,就可以從聲明處起合理地使用該變數了。"extern”起到了擴充範圍的作用。

//.c#include <stdio.h>void main(){    extern A;//用extern聲明外部變數;若變數為int類型,類型名可寫也可以省略。    printf("%d", A);}int A=100;

b.在多檔案的程式中,如果多個檔案都要使用同一個外部變數,不能在各個檔案中各定義一個外部變數,否則會出現“重複定義”的錯誤。正確的做法是:在任一個檔案中定義外部變數,其他檔案用 "extern”對變數做“外部變數聲明”。在編譯和串連時,系統會由此知道該變數是一個已經在別處定義的外部變數,並把另一檔案中外部變數的範圍擴充到本檔案,這樣在本檔案就可以合法地使用該外部變數了。

//file1.c#include <stdio.h>int A = 100;//定義外部變數void main(){    printf("%d",power());}//file2.cextern A;//聲明A為一個已定義的外部變數int power(){    return A*A;}

extern只用作聲明,而不用於定義。extern說明變數或者函數定義在其他的源檔案裡,而不用include標頭檔的方式來引用該函數,在連結時,連結器在各個模組中搜尋這個變數或者函數來進行最終連結。
c.外部函數
在定義函數時,如果在最左端加關鍵字extern,表示此函數是外部函數。C語言規定,如果在定義時省略extern,則隱含為外部函數。而內建函式必須前加static關鍵字;
在需要調用此函數的檔案中,用extern對函數作聲明,表示該函數是在其他檔案中定義的外部函數。
"C”的含義:(extern “C”)
C++通過函數參數的不同類型支援重載機制,編譯器根據參數為每個重載函數產生不同的內部標識符。例如編譯器為void Eat(Beef …);void Eat(Fish …);void Eat(Chicken …);三個Eat 函數產生象_eat_beef、_eat_fish、_eat_chicken 之類的內部標識符(不同的編譯器可能產生不同風格的內部標識符)。
如果 C++程式要調用已經被編譯後的C 函數,該怎麼辦?
假設某個 C 函數的聲明如下:

void foo(int x, int y);

該函數被C 編譯器編譯後在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字用來支援函數重載和型別安全串連。由於編譯後的名字不同,C++程式不能直接調用C 函數。C++提供了一個C串連交換指定符號extern“C”來解決這個問題。
例如:

extern “C”{void foo(int x, int y);… // 其它函數}或者寫成extern “C”{#include “myheader.h”… // 其它C 標頭檔}

這就告訴C++編譯譯器,函數foo 是個C 串連,應該到庫中找名字_foo 而不是找_foo_int_int。C++編譯器開發商已經對C 標準庫的標頭檔作了extern“C”處理,所以我們可以用#include 直接引用這些標頭檔。

2.extern "C"程式執行個體

假設有C檔案:

//c.h#ifndef _C_H_#define _C_H_extern int add(int x, int y);#endif
//c.cint add(int x, int y){    return x+y;}

在C++下調用add()函數

//cplusplus.cpp#include <iostream>#include "c.h"using namespace std;void main(){    add(1, 0);    system("Pause");}

產生錯誤:無法解析的外部符號 "int __cdecl add(int,int)" (?add@@YAHHH@Z),該符號在函數 _main 中被引用
為瞭解決這個問題,我們需要使用extern "C"。改寫C檔案

//c.h#ifndef _C_H_#define _C_H_#ifdef __cplusplusextern "C" {#endifextern int add(int x, int y);#ifdef __cplusplus}#endif#endif

檔案為*.c,__cplusplus沒有被定義,extern "C" {}這時沒有生效,對於C語言只是extern int add(int, int);而編譯c++源檔案,__cplusplus被定義,對於C++他看到的是extern "C" {extern int add(int, int);},編譯器就會知道add(1, 0)調用的是C串連。
最後:很多DLL的組建檔案(XXX.c)中常出現extern "C" ,windows採用C語言編譯建立dll,C程式可以正確調用DLL,而當使用者使用C++調用DLL時,extern "C" {}就起作用了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.