雖然定義也是聲明,但為了方便說明問題,下文中的聲明只是單純的聲明,定義就只是定義。
1. 聲明、定義、初始化和賦值四個(gè)術(shù)語有著本質(zhì)的不同,雖然有時(shí)候看起來差不多甚至完全一樣,但如果不搞清楚很容易出現(xiàn)錯(cuò)誤,或者錯(cuò)了不知道怎么改。
2. a: extern關(guān)鍵詞用來表明這是一個(gè)聲明:extern int I;變量i就是一個(gè)聲明。聲明前面一定要有一個(gè)關(guān)鍵字extern,沒有這個(gè)關(guān)鍵詞就不是一個(gè)聲明。
b: 沒有extern就是一個(gè)定義,比如int i=9;是一個(gè)定義,特別要注意的是int i;這也是一個(gè)定義。
c: 初始化就是在變量定義時(shí)給變量一個(gè)初值,所以初始化語句也一定是一個(gè)定義語句,但反過來就不對(duì)了,因?yàn)轭愃朴冢?/span>int i;就是定義,但沒有初始化。特別要注意的是:extern int i = 9;雖然有extern關(guān)鍵詞,但是因?yàn)槌跏蓟耍赃@也是一個(gè)定義,不是聲明。
d: 賦值語句就簡單了,賦值語句是給一個(gè)已經(jīng)定義的變量(不管這個(gè)變量有沒有初始化)一個(gè)新值。特別要注意的是,要給賦值的變量必須已經(jīng)定義過了,僅僅聲明是不行的。
3. extern關(guān)鍵詞除了表明這是一個(gè)聲明以外,更重要的是表明:所聲明的變量的定義可能是在程序中其他文件里。如下代碼
//file1.cpp
#include <iostream>
using namespace std;
extern int i;//這是一個(gè)聲明,告訴編譯器變量i的定義有可能是在其他源文件中,即使本文件中沒有i的定義,你也不要報(bào)錯(cuò)。
void main()
{
extern int i;//同樣是對(duì)i的聲明,作用與上面的聲明完全一樣,說明聲明可以存在多個(gè),實(shí)際上這兩個(gè)聲明只要任意一個(gè)就可以了。但是兩個(gè)聲明語句如果一個(gè)都沒有,編譯器就會(huì)認(rèn)為變量i沒有定義,會(huì)報(bào)錯(cuò)。
i=0;//賦值語句,給變量i一個(gè)新值,變量賦值前必須要已經(jīng)定義了,如果不存在file2文件中的定義語句,雖然不會(huì)出現(xiàn)編譯錯(cuò)誤,但是鏈接會(huì)有錯(cuò)。
cout<<i;
}
//file2.cpp
int i;//首先是一個(gè)定義,而且是一個(gè)沒有初始化的定義(不過實(shí)際上全局變量i被默認(rèn)初始化為0),變量i被定義在file2源文件中
4. 一個(gè)程序中可能包括不只一個(gè)文件,所有文件中同一個(gè)變量(其實(shí)主要說的全局變量)必須總共只能定義一次,但是聲明可以有無數(shù)個(gè)。而且如果文件A中用到的變量的定義是在其他文件中,那么在文件A中用這個(gè)變量之前,一定要加上一句extern聲明語句,告訴編譯器我所用的這個(gè)變量有可能是在其他文件里
5. extern int i=9;上面已經(jīng)提到雖然有extern,但這也是一個(gè)定義,因?yàn)槌跏蓟恕?span style="color: red; ">類似于這種有extern也有初始化的語句,只能出現(xiàn)在全局作用域,如果出現(xiàn)在函數(shù)內(nèi)部,這是錯(cuò)誤的。
6. (轉(zhuǎn))有關(guān)編譯器的一個(gè)特點(diǎn):現(xiàn)代編譯器一般都屬于按文件編譯,就是說編譯時(shí)多個(gè)源文件自己編譯自己的,互不影響,好像只有自己一個(gè)文件。只要每個(gè)文件編譯時(shí)沒有出現(xiàn)錯(cuò)誤,那么就不會(huì)發(fā)生編譯時(shí)錯(cuò)誤。但是沒有發(fā)生編譯錯(cuò)誤,并不代表程序就沒有錯(cuò)誤,因?yàn)檫€會(huì)發(fā)生鏈接錯(cuò)誤。比如下面這兩個(gè)代碼
//A.cpp
int i;//這是變量i的定義
void main()
{
}
//B.cpp
int i;//這也是變量i的定義
編譯時(shí)兩個(gè)文件A和B是相互不影響的,所以編譯時(shí)不會(huì)出現(xiàn)任何錯(cuò)誤,但是這個(gè)程序是有問題的,因?yàn)槿肿兞縤是被定義了兩次的,所以鏈接時(shí)就會(huì)報(bào)告類似于下面的錯(cuò)誤:
B.obj : error LNK2005: "int i" (?i@@3HA) already defined in A.obj
Debug/A.exe : fatal error LNK1169: one or more multiply defined symbols found
另外上面也提到了,編譯時(shí)各個(gè)文件是相互不影響的,編譯器是不會(huì)認(rèn)為在這個(gè)文件中沒有定義的變量其實(shí)很有可能人家是個(gè)全局變量,在其他文件中定義了,這就要報(bào)錯(cuò)。解決方法就是用extern聲明一個(gè)變量,告訴編譯器人家這個(gè)變量不是沒有定義,只是在其他文件中定義了,你別報(bào)錯(cuò)了。