原文連結:http://blog.csdn.net/hangyu628/article/details/3854487
變數的定義分配了變數的儲存空間,並有可能賦一個初始值給變數,在程式中變數只能定義一次; (如int i; 或 int i=1;)變數的聲明主要聲明了變數名和變數類型,沒有分配空間定義也是一種聲明。當在定義一個變數時,我們指出了其名稱與類型。我們不能沒定義一個變數就使用extern來聲明它,在程式中可以聲明多次。 (如extern int i; extern int i;).
只要聲明存在初始值,就被認為定義,不管是否有extern(例:extern int i=2是定義)
----引用自:C++primer:還有一點全域變數預設編譯器會自動為其賦值為0,而局部變數必須手動賦值
一、一般情況,在a.cpp定義一個t,然後在a_pub.h用extern聲明它,在b.cpp include a_pub.h使用,如下情況
1.第一種情況:編譯出錯
//Out_pub.h extern int t=1; //屬於定義//Out.cppint t; //定義一個全域變數,預設值為0,也可以改:int t=1;//test.cpp#include <iostream>#include "Out_pub.h" int main(){ std::cout<<t<<std::endl; return 0;}
2.第二種情況:
上面第二個程式,main函數內自己再定義一個int t=3,不會出錯,因為內部的定義會屏蔽外部(全域)的定義extern還可以聲明函數,具體用法和聲明變數一樣
//Out_pub.h extern int t; //屬於聲明,可以有多個聲明extern int t; //多加幾個也正常.//Out.cppint t; //定義一個全域變數,預設值為0,也可以改:int t=1;//test.cpp#include <iostream>#include "Out_pub.h" int main(){ std::cout<<t<<std::endl; return 0;}
二、也可在a.cpp定義,直接在b.cpp引用它,如下情況
//Out.cppint t; //定義一個全域變數,預設值為0,也可以改:int t=1;//test.cpp#include <iostream> extern int t; //聲明一個外部的,若改為extern int i=2; 則重定義 int main(){ std::cout<<t<<std::endl; return 0;}
三、extern的另一個用法:用於C++編譯器,來編譯extern的C函數時,出現問題的。
原因,C++為瞭解決多態,會將函數名與參數合一起產生中間函數,此時若用C,也產生中間函數,所以編譯時間會出錯
例:
//Out.h#ifdef __cplusplus //該段代碼引用網上的..., extern "C"{#endif #include <stdio.h> //若 Out.h裡 直接#include <stdio.h> extern void aa();// extern void aa(); //出錯:unresolved external symbol "void __cdecl aa(void)" (?aa@@YAXXZ),在VC6調試結果#ifdef __cplusplus}#endif//Out.c#include "Out.h"void aa(){ printf("aa is running");}//Test.cpp#include <iostream>using namespace std;#include "Out.h"int main(){ aa(); return 0;}
四、const預設是局部變數,即使是在全域中申明也一樣,且在定義時,必須賦予初值。若想在外部參考,必須加extern
例子:
//a.cppextern const int a=100;//b.cppextern const int a; //引用a.cpp中的
const 之所以放於head檔案,且預設為局部變數:編譯時間,const變數將被常量運算式所替代。不儲存任何空間為const變數。而若const變數不是用常量運算式所初始化的話,則不應該定義在head,而應該定義在cpp,然後用extern在head聲明