第二章 数组名是一个指针常量吗?
數組名是一個指針常量這種觀點來源于數組名在表達式計算中與指針的結果等效性。例如下面的代碼:
?
int a[10], *p = a, *q;
q = a + 1;
q = p + 1;
?
在效果上看,a + 1與 p + 1是相同的,這很容易給人一種a就是p的假象,但,這僅僅是假象。鑒于指針常量包含了指針和常量兩類概念,我們可以把這個問題分開兩部分進行討論。
?
一、數組名是指針嗎?
?
在《C與指針》一書中,作者用一個著名的例子闡述了數組名與指針的不同。在一個文件中定義:int a[10];然后在另一個文件中聲明:extern int *a; 筆者不在這里重復其中的原理,書中的作者試圖從底層操作上闡述數組名與指針的不同點,但筆者認為這個例子存在一些不足,a在表達式中會轉換為一個非對象的符號地址,而指針a卻是一個對象,用一個非對象去跟一個對象比較,有“偷跑”的嫌疑,這個例子只是說明了數組名的非對象性質,只能證明對象與非對象實體在底層操作上的不同,事實上,如上一章所述,指針也有非對象形態。筆者認為,無須從底層的角度上花費那么多唇舌,僅僅從字面上的語義就可以推翻數組名是一個指針的觀點。
?
首先,在C/C++中,數組類型跟指針類型是兩種不同的派生類型,數組名跟指針是兩種不同類型的實體,把數組類型的實體說成“是”另一個類型的實體,本身就是荒謬的;
?
其次,a + 1在效果上之所以等同于p + 1,是因為a進行了數組到指針的隱式轉換,這是一個轉換的過程,是converted to而不是is a的過程。如果是兩個相同的事物,又怎會有轉換的過程呢?當把a放在a + 1表達式中時,a已經從一個數組名轉換為一個指針,a是作為指針而不是數組名參與運算的;
?
第三,a + 1與p + 1是等效關系,不是等價關系。等價是相同事物的不同表現形式,而等效是不同事物的相同效果。把數組名說成是指針實際上把等效關系誤解為等價關系。
?
因此,數組名不是指針,永遠也不是,但在一定條件下,數組名可以轉換為指針。
?
二、數組名是一個常量嗎?
?
看見這句話有人會覺得奇怪,數組定義之后就不能改變了,數組名不就是個常量嗎?在表達式中,數組名的確可以轉換為一個不變的符號地址,但在C中,不變的實體不一定是常量!而且,C/C++有常量與常量表達式之分,常量與常量表達式是兩種不同的實體,但常量表達式可以作為常量使用。C/C++中的常量雖然有所不同,但都不包括數組或數組名,而且數組名也不一定是常量表達式。
?
請在C90的編譯器中編譯如下代碼,注意不能是C99和C++的,因為C99和C++不再規定數組的初始化器必須是常量表達式,會看不到效果:
?
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為什么不能通過編譯?是由于自動數組名并不是常量表達式。在C中,常量表達式必須是編譯期的,只在運行期不變的實體不是常量表達式,請看標準的摘錄:
?
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是自動數組,首地址在編譯期是不可知的,因為這樣的對象在編譯期還不存在;a和b是靜態數組,靜態對象從程序開始時就已存在,因此a和b的首地址在編譯期是已知的,它們都屬于常量表達式中的地址常量表達式。
?
所以,C/C++中的數組名,都不是常量。C中的數組名,是否常量表達式要視其存儲連續性而定,全局數組、靜態數組名都是常量表達式,而自動數組名不是。在C++中,由于不再規定常量表達式必須是編譯期的,因此C++的數組名都是常量表達式。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/supermegaboy/archive/2009/11/23/4855018.aspx
總結
以上是生活随笔為你收集整理的第二章 数组名是一个指针常量吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一章:数组与指针概念剖析
- 下一篇: 维度及长度均可任意变形的动态数组