C C 中extern關鍵字

2022-09-19 05:24:06 字數 3123 閱讀 7444

當extern與"c"一起連用時,如:extern "c" void fun(int a, int b); 這就告訴編譯器在編譯fun這個函式名時按著c的規則去翻譯相應的函式名而不是c++的,c++的規則在翻譯這個函式名時會把fun這個名字弄得面目全非,例如:fun@abc_isdnfsdf#%&,不同編譯器採取的翻譯方法不一樣。這麼做的原因因為c++支援函式過載

下面是乙個標準的寫法:

#ifdef __cplusplus

#if __cplusplus

extern "c"

#endif

#endif /*__cplusplus*/

當extern不與"c"一起修飾變數或函式,例如在標頭檔案中:extern int f_int; 它的作用就是宣告函式全域性變數作用範圍的關鍵字,其宣告的函式和變數可以在本模組或其他模組中使用,一定要切記是宣告

例:當b模組(編譯單元)引用a模組(編譯單元)中定義的全域性變數或函式時,它只要包含a模組的標頭檔案即可,在編譯階段,模組b雖然找不到該函式或變數,但不會報錯,它會在鏈結時從模組a生成的目標**中找到該函式。

#ifdef test1h

#define test1h

extern char g_str;//宣告全域性變數

void fun1();

#endif

(2)在test1.cpp中

#include "test1.h"

char g_str = "123456";//定義全域性變數

void fun1()

#include "test1.h"

void fun2()

此時若開啟test1.obj,你可以在裡面找到"123456"這個字串,但是你卻不能在test2.obj中找到它,因為g_str為整個工程專案的全域性變數,在記憶體中只存在乙份,如果test2.obj也有乙份,會在鏈結時報告重複定義錯誤。

(4)當全域性變數宣告與定義放在一起時,例如把test1.h改為:

extern char g_str = "123456";//此時相當於無extern

然後令test1.cpp中的定義去掉,此時再編譯鏈結test1和test2兩個模組時,會報鏈結錯誤,這是因為全域性變數g_str的定義放到了標頭檔案中,test1.cpp與test2.cpp同時包含test1.h,此時鏈結器在鏈結test1和test2時發現了兩個g_str,造成重複定義。

解決這個問題的辦法是:把test2的**中的#include "test1.h"去掉換成

extern char g_str;

void fun2()

這時編譯器就知道g_str是引自於外部的乙個編譯模組不會在本模組再重複定義乙個出來,但是這麼做其實非常糟糕,因為你由於無法在test2.cpp中使用#include "test1.h",那麼test1.h宣告的其他函式你也無法使用,除非都用extern宣告,你會寫一大堆無效**且這與標頭檔案對外提供介面的初衷背離,所以,謹記:在標頭檔案中只做宣告

#ifndef test1h

#define test1h

static cahr g_str = "123456";

void fun1();

#endif

(2)test1.cpp:

#include "test1.h"

void fun1()

(3)test2.cpp:

void fun2()
以上兩個編譯單元可以鏈結成功,當你開啟test1.obj時,可以在其中找到字串「123456」,同時,也能在test2.obj中找到他們,之所以能鏈結成功而沒有報重複定義,是因為雖然他們有相同的內容,但是儲存的實體地址不同,就像兩個不同的變數賦給了相同的值,而這兩個變數分別作用於它們各自的編譯單元。

此時如果你想探查到底,跟蹤除錯上述**,結果你可以會發現兩個編譯單元的g_str的記憶體位址相同。這可與我們總結的嚴重不符,原因在哪呢?其實這是編譯器在欺騙你,大多數編譯器都有**優化功能,以達成生成的目標程式更節省記憶體,執行效率更高,當編譯器在連線各個單元的時候,它會把相同內容的記憶體只拷貝乙份,就例如上述的「123456」。

下列的**能夠馬上拆穿這個謊言:

(1)test1.cpp:

#include "test1.h"

void fun1()

(2)test2.cpp:

#include "test1.h"

void fun2()

(3)main.cpp:

void main()
此時在跟蹤**時,就會發現兩個編譯單元中的g_str位址並不相同,因為你在一處修改了它,所以編譯器強行恢復記憶體的原貌,在記憶體中存在了兩份拷貝給兩個模組。正因為static有這樣的特性,所以一般定義static全域性變數時,都把它放在原始檔而不是標頭檔案,這樣就不會給其他模組造成不必要的資訊汙染。

const可以與extern連用來宣告該常量可以作用於其他編譯模組中,標頭檔案中extern const char g_str;,然後在原始檔定義const char g_str = "123456"

所以當const單獨使用時與static相同,而當與extern連用時,特性就跟extern的一樣了。

內容總結於博主chao_yu

C C 中extern關鍵字

extern關鍵字可置於變數或者函式前,以表示變數或者函式的定義在別的檔案中,提示編譯器遇到此變數或函式時,在其它模組中尋找其定義。另外,extern也可用來進行鏈結指定。在介紹外部變數之前,先來看一下什麼是區域性變數。下面是乙個例子。include define maxline 1000 int ...

C C 中extern關鍵字詳解

一.extern修飾變數和函式 在c語言中,修飾符extern用在變數或者函式的宣告前,用來說明 此變數 函式是在別處定義的,要在此處引用 extern宣告不是定義,即不分配儲存空間。先來看一段 basic stdy.h ifndef basic stdy h define basic stdy h...

C C 的extern關鍵字

比如這是我的myextern.cpp檔案,只有一行 int ex 3 然後這是我的main.cpp include using namespace std intmain 如果我在main中加extern關鍵字 include using namespace std intmain 也就是說在沒有用...