數(shù)組名是一個(gè)指針常量這種觀點(diǎn)來源于數(shù)組名在表達(dá)式計(jì)算中與指針的結(jié)果等效性。例如下面的代碼:
int a[10], *p = a, *q;
q = a + 1;
q = p + 1;
在效果上看,a + 1與 p + 1是相同的,這很容易給人一種a就是p的假象,但,這僅僅是假象。鑒于指針常量包含了指針和常量?jī)深惛拍?,我們可以把這個(gè)問題分開兩部分進(jìn)行討論。
一、數(shù)組名是指針嗎?
在《C與指針》一書中,作者用一個(gè)著名的例子闡述了數(shù)組名與指針的不同。在一個(gè)文件中定義:int a[10];然后在另一個(gè)文件中聲明:extern int *a; 筆者不在這里重復(fù)其中的原理,書中的作者試圖從底層操作上闡述數(shù)組名與指針的不同點(diǎn),但筆者認(rèn)為這個(gè)例子存在一些不足,a在表達(dá)式中會(huì)轉(zhuǎn)換為一個(gè)非對(duì)象的符號(hào)地址,而指針a卻是一個(gè)對(duì)象,用一個(gè)非對(duì)象去跟一個(gè)對(duì)象比較,有“偷跑”的嫌疑,這個(gè)例子只是說明了數(shù)組名的非對(duì)象性質(zhì),只能證明對(duì)象與非對(duì)象實(shí)體在底層操作上的不同,事實(shí)上,如上一章所述,指針也有非對(duì)象形態(tài)。筆者認(rèn)為,無須從底層的角度上花費(fèi)那么多唇舌,僅僅從字面上的語義就可以推翻數(shù)組名是一個(gè)指針的觀點(diǎn)。
首先,在C/C++中,數(shù)組類型跟指針類型是兩種不同的派生類型,數(shù)組名跟指針是兩種不同類型的實(shí)體,把數(shù)組類型的實(shí)體說成“是”另一個(gè)類型的實(shí)體,本身就是荒謬的;
其次,a + 1在效果上之所以等同于p + 1,是因?yàn)?span lang="EN-US">a進(jìn)行了數(shù)組到指針的隱式轉(zhuǎn)換,這是一個(gè)轉(zhuǎn)換的過程,是converted to而不是is a的過程。如果是兩個(gè)相同的事物,又怎會(huì)有轉(zhuǎn)換的過程呢?當(dāng)把a放在a + 1表達(dá)式中時(shí),a已經(jīng)從一個(gè)數(shù)組名轉(zhuǎn)換為一個(gè)指針,a是作為指針而不是數(shù)組名參與運(yùn)算的;
第三,a + 1與p + 1是等效關(guān)系,不是等價(jià)關(guān)系。等價(jià)是相同事物的不同表現(xiàn)形式,而等效是不同事物的相同效果。把數(shù)組名說成是指針實(shí)際上把等效關(guān)系誤解為等價(jià)關(guān)系。
因此,數(shù)組名不是指針,永遠(yuǎn)也不是,但在一定條件下,數(shù)組名可以轉(zhuǎn)換為指針。
二、數(shù)組名是一個(gè)常量嗎?
看見這句話有人會(huì)覺得奇怪,數(shù)組定義之后就不能改變了,數(shù)組名不就是個(gè)常量嗎?在表達(dá)式中,數(shù)組名的確可以轉(zhuǎn)換為一個(gè)不變的符號(hào)地址,但在C中,不變的實(shí)體不一定是常量!而且,C/C++有常量與常量表達(dá)式之分,常量與常量表達(dá)式是兩種不同的實(shí)體,但常量表達(dá)式可以作為常量使用。C/C++中的常量雖然有所不同,但都不包括數(shù)組或數(shù)組名,而且數(shù)組名也不一定是常量表達(dá)式。
請(qǐng)?jiān)?span lang="EN-US">C90的編譯器中編譯如下代碼,注意不能是C99和C++的,因?yàn)?span lang="EN-US">C99和C++不再規(guī)定數(shù)組的初始化器必須是常量表達(dá)式,會(huì)看不到效果:
int main( void )
{
static int a[10], b[10];
int c[10], d[10];
int* e[] = { a, b }; /* A */
int* f[] = { c, d }; /* B */
return 0;
}
B為什么不能通過編譯?是由于自動(dòng)數(shù)組名并不是常量表達(dá)式。在C中,常量表達(dá)式必須是編譯期的,只在運(yùn)行期不變的實(shí)體不是常量表達(dá)式,請(qǐng)看標(biāo)準(zhǔn)的摘錄:
6.6 Constant expressions
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
c和d是自動(dòng)數(shù)組,首地址在編譯期是不可知的,因?yàn)檫@樣的對(duì)象在編譯期還不存在;a和b是靜態(tài)數(shù)組,靜態(tài)對(duì)象從程序開始時(shí)就已存在,因此a和b的首地址在編譯期是已知的,它們都屬于常量表達(dá)式中的地址常量表達(dá)式。
所以,C/C++中的數(shù)組名,都不是常量。C中的數(shù)組名,是否常量表達(dá)式要視其存儲(chǔ)連續(xù)性而定,全局?jǐn)?shù)組、靜態(tài)數(shù)組名都是常量表達(dá)式,而自動(dòng)數(shù)組名不是。在C++中,由于不再規(guī)定常量表達(dá)式必須是編譯期的,因此C++的數(shù)組名都是常量表達(dá)式。
聯(lián)系客服