我想了解外部連接和內部連接及其區別。 ios
我也想知道 c++
除非默認聲明爲
extern
,不然默認狀況下const
變量內部連接。 函數
編寫實現文件( .cpp
, .cxx
等)時,編譯器會生成翻譯單元 。 這是實現文件中的目標文件,以及#include
在其中的全部標頭。 spa
內部連接僅指翻譯單元範圍內的全部內容。 翻譯
外部連接是指存在於特定翻譯單元以外的事物。 換句話說, 能夠經過整個程序訪問 ,這是全部翻譯單元(或目標文件)的組合。 code
正如dudewat所說, 外部連接意味着在整個程序中均可以訪問符號(函數或全局變量),而內部連接意味着只能在一個翻譯單元中對其進行訪問。 對象
您可使用extern
和static
關鍵字顯式控制符號的連接。 若是未指定的聯動是默認鍵是extern
用於非const
符號和static
(內部)爲const
的符號。 ci
// in namespace or global scope int i; // extern by default const int ci; // static by default extern const int eci; // explicitly extern static int si; // explicitly static // the same goes for functions (but there are no const functions) int foo(); // extern by default static int bar(); // explicitly static
請注意,與其使用static
進行內部連接,不如使用匿名名稱空間 ,也能夠將class
es放入其中。 在C ++ 98和C ++ 11之間,用於匿名名稱空間的連接已更改,但主要的問題是,其餘翻譯單元沒法訪問它們。 作用域
namespace { int i; // external linkage but unreachable from other translation units. class invisible_to_others { }; }
extern
聲明,能夠將其範圍擴展到除包含它以外的文件。 static
來將全局變量的範圍限制爲包含聲明的文件。 聽說這些變量具備內部聯繫 。 考慮如下示例: get
void f(int i); extern const int max = 10; int n = 0; int main() { int a; //... f(a); //... f(a); //... }
f
聲明f
與外部鏈接 (默認值)的功能。 必須稍後在此文件或其餘翻譯單元(以下所示)中提供其定義。 max
定義爲整數常量。 常量的默認連接是internal 。 使用關鍵字extern
將其連接更改成外部。 所以,如今能夠在其餘文件中訪問max
。 n
被定義爲整數變量。 在函數體外部定義的變量的默認連接爲external 。 #include <iostream> using namespace std; extern const int max; extern int n; static float z = 0.0; void f(int i) { static int nCall = 0; int a; //... nCall++; n++; //... a = max * z; //... cout << "f() called " << nCall << " times." << endl; }
max
聲明具備外部連接 。 max
的匹配定義(具備外部連接)必須出如今某些文件中。 (如1.cpp中所示) n
被聲明具備外部連接 。 z
定義爲具備內部連接的全局變量。 nCall
指定nCall
是保持其在調用值函數的變量f()
。 與具備默認自動存儲類的局部變量不一樣, nCall
在程序開始時僅初始化一次,而對於每次調用f()
nCall
不會初始化一次。 存儲類說明符static
影響局部變量的生存期,而不影響其範圍。 注意:關鍵字static
具備雙重做用。 在全局變量的定義中使用時,它指定內部連接 。 當在局部變量的定義中使用時,它指定變量的生存期將是程序的持續時間,而不是函數的持續時間。
但願有幫助!
讓咱們來談談「 C」中的不一樣範圍
範圍:基本上,我能夠看到多長時間以及多遠。
局部變量:做用域僅在函數內部。 它位於RAM的STACK區域中。 這意味着每次調用一個函數時,該函數的全部變量(包括函數參數)都會從新建立,並在控件退出該函數後銷燬。 (由於每次函數返回時堆棧都會被刷新)
靜態變量:此範圍適用於文件。 它能夠在文件中的任何位置訪問
在其中聲明。 它位於RAM的DATA段中。 因爲只能在文件內部進行訪問,所以只能進行內部連接。 任何
其餘文件看不到該變量。 實際上,STATIC關鍵字是咱們能夠引入某些級別的數據或功能的惟一方法
隱藏在「 C」中
全局變量:此範圍適用於整個應用程序。 它能夠從應用程序的任何位置訪問。 全局變量也駐留在DATA段中,由於能夠在應用程序中的每一個位置訪問它,所以能夠進行EXTERNAL連接
默認狀況下,全部功能都是全局的。 若是須要從外部隱藏文件中的某些功能,則能夠在該功能的前面加上static關鍵字。 :-)
在談論這個問題以前,最好準確地瞭解術語翻譯單元 , 程序和C ++的一些基本概念 (實際上,連接一般是其中之一)。 您還必須知道什麼是範圍 。
我會強調一些要點,特別是。 先前答案中缺乏的那些。
連接是名稱的屬性,由聲明引入。 不一樣的名稱能夠表示相同的實體 (一般是對象或函數)。 所以,談論實體的連接一般是胡說八道,除非您肯定該實體將僅由某些特定聲明(不過一般是一個聲明)中的惟一名稱引用。
請注意, 對象是實體,但變量不是。 在討論變量的連接時,實際上要關注所表示實體的名稱(由特定聲明引入)。 名稱的連接是如下三種之一:無連接,內部連接或外部連接。
不一樣的翻譯單元能夠經過頭文件/源文件共享相同的聲明(是的,這是標準的措詞)。 所以,您能夠在不一樣的翻譯單位中使用相同的名稱。 若是聲明的名稱具備外部連接,則該名稱引用的實體的身份也將共享。 若是聲明的名稱具備內部連接,則不一樣翻譯單位中的相同名稱表示不一樣的實體,可是您能夠在同一翻譯單位的不一樣範圍內引用該實體。 若是名稱沒有連接,則根本沒法從其餘範圍引用該實體。
(糟糕...我發現我鍵入的內容只是在重複標準措辭 ...)
語言規範中尚未涵蓋其餘一些使人困惑的地方。
__attribute__
或__declspec
)或編譯器選項在內部在該映像中指定,而且該映像不是整個程序或目標文件從翻譯單元翻譯過來的,所以沒有標準的概念能夠準確地描述它。 由於符號不是C ++中的規範術語,因此它僅是實現細節,即便方言的相關擴展可能已被普遍採用。 名稱空間範圍const
變量的連接規則是特殊的(特別不一樣於C語言中在文件範圍中聲明的const
對象,該對象也具備標識符連接的概念)。 因爲ODR是由C ++強制執行的, 所以對於整個程序中發生的同一變量或函數,除了inline
函數外,不要超過一個定義 , 這一點很重要 。 若是沒有這樣特殊的const
規則,則最簡單的const
變量聲明在多個翻譯單元(或一個翻譯單元包含)的頭文件或源文件(一般是「頭文件」)中帶有初始化程序(例如= xxx
)程序中會屢次(儘管不多)違反ODR,這使得沒法使用const
變量替換某些相似於對象的宏。