陣列與指標的藝術 第三章 陣列的解剖學

2021-05-21 21:43:22 字數 2430 閱讀 1103

注意:本系列文章** csdn部落格 http://blog.csdn.net/supermegaboy/archive/2009/11/23/4855027.aspx

感謝飛天御女豬大牛!

c/c++的陣列不同於vb等語言的陣列,是有層次的,這個層次指的不是維度,而是象俄羅斯有名的套娃一樣,一維套一維,亦即陣列的巢狀,陣列的元素也是陣列,vb等語言的陣列與之相比更像乙個平面。

陣列巢狀這個現象從其它語言的角度來看有點奇特,但其實原因也很簡單。c/c++的物件模型並不視陣列為某種數值的簡單集合,而是物件的聚集,每個元素都是乙個物件。元素為整數物件,就是整數陣列,為浮點數物件,就是浮點數陣列。然而,陣列本身也是一種物件,因此乙個陣列也能作為另乙個陣列的元素。當某個一維陣列以一維陣列作為元素時,這個一維陣列每個元素都具有陣列型別,這個一維陣列其實是二維陣列,同理,乙個以二維陣列作為元素的一維陣列其實是三維陣列。因此,使用c/c++陣列的時候應該用陣列巢狀的觀點去看待。有人據此認為,c/c++的陣列不是真正的陣列,還有的認為c/c++沒有多維陣列,這些觀點都有失偏頗,與其它語言的陣列相比,兩者只是同一事物的不同例項,是實現方法的不同,而本質是一樣的,c/c++的陣列巢狀可視為對陣列概念的發展。

現在來看看陣列的定義:

6.5.4.2 array declarators

semantics

if, in the declaration 「t dl.」 dl has the form

d [ constant expressionopt ]

這個定義非常簡單,其中t代表元素型別,d代表識別符號,constant expression必須為大於0的常量表示式,opt表示可選,即中的內容可以為空,當為空時叫不完整型別,表示這個陣列物件的長度未知,不完整陣列型別可以在程式的某個地方補充完整。細心的人馬上就會發現,從形式上看,怎麼只有一維陣列的定義?這個形式如何定義多維陣列?剛才說過,c/c++的陣列是陣列的巢狀,因此多維陣列的定義也反映了這個本質。多維陣列的定義是通過巢狀的一維陣列定義構造的。對於一維陣列:

t d[m]

當元素為一維陣列t[n]時,元素的型別也為陣列型別,用t[n]代替t,則為:

t[n] d[m]

這個語法結構不符合c/c++陣列定義的語法形式,將[n]移動到[m]後,就是正式的二維陣列的定義了:

t d[m][n]

其中d[0]---d[m-1]都是一維陣列,具有陣列型別t[n]。各種維度的多維陣列可以用同樣的巢狀方法構造出來。

乙個一維陣列t[m],經過陣列到指標的轉換後,型別轉換為t*,二維陣列t[m][n]轉換為指標後,型別轉換為t ( * )[n],有些初學者對t( * )[n]這種形式較難理解,怎麼多了一維,形式就有這麼大的差別呢,其實原理還是跟巢狀有關,二維陣列為一維陣列的巢狀,元素為陣列型別,因此用t[n]代替t,則二維陣列轉換之後的指標型別為t[n] *,將[n]移動到*的右邊,就是t*[n],由於的優先順序比*高,因此需要加括號,就成為t( * )[n]了,否則就不是指標型別,而成了指標陣列型別了。

圍繞陣列名,存在一些有趣的表示式,下面的內容通過討論這些表示式中較為重要的幾個,來加深對陣列的理解。對於二維陣列:

t a[m][n]

&a:是乙個指向二維陣列物件的指標,型別為t ( * )[m][n]。在c標準出現之前,一些早期的實現並不允許&a,因為這些編譯器認為此時的a轉換為乙個右值,而&運算子要求乙個左值,因此非法。c標準委員會鑑於物件的概念已經得到了擴充套件,而且允許&a並沒有害處,因此把&運算子作為乙個例外寫進了陣列到指標的轉換條款中。這種情況下的a代表陣列物件,&a表示對陣列物件取位址,因此&a的結果跟a是相同的,但型別不同。

筆者曾經見過某些觀點認為,&a才是陣列的首位址,不是a。這個觀點初看起來似乎很有道理,乙個陣列物件的引用,不正是首位址嗎?但實際上這種論述是不符合標準的,陣列到指標的轉換條款規定,當產生乙個points to the initial element of the array object的時候,其前提是由array of type到pointer to type的轉換,但&a的型別屬於pointer to array of type,不是pointer to type,因此真正代表陣列首位址的是a本身,不是&a。

&a[0][0]:這是陣列首元素的位址。&a[0][0]常常被誤解為陣列a的首位址,其實a[0][0]只不過由於位置特殊,其位址值才與a相同,&a[0][0]是乙個t型別物件的引用,不是乙個陣列物件的引用,而且其型別不是由array of type轉換得來的,因此其意義不是陣列首位址。

a[i](其中 i >= 0 && i < m):從陣列巢狀的觀點來看,a是乙個一維陣列,元素的型別為陣列型別,因此a[i]的型別為t[n],在表示式中轉換為t*,是第i個一維陣列的首位址。

a + 1:a隱式轉換為指標型別t( * )[n]然後加1,請記住指標加法是以指標指向物件的大小為步長的,因此a + 1將跨過n * sizeof( t )個位元組。

&a + 1:與a + 1同理,&a型別為t( * )[m][n],因此&a + 1的步長為m * n * sizeof( t )。

第三章 棧 佇列 陣列

1.假設棧初始為空,將中綴表示式 這題和上題區別就是rear指向隊尾元素,而不是隊尾元素的下乙個元素 4.設有下圖所示的火車車軌,入口到出口之間有n條軌道,列車的行進方向均為從左至右,列車可駛入任意一條軌道。現有編號為1 9的9列列車,駛入的次序依次是8,4,2,5,3,9,1,6,7。若期望駛出的...

第三章 多維陣列專題

一 編寫一段程式,用整形陣列初始化乙個vector物件。include include include using namespace std int main vectorv1 a,a 10 for int i 0 i 10 i 二 編寫一段程式,將含有整數元素的vector物件拷貝給乙個整型陣列...

小駱駝 第三章 列表與陣列

列表 usr bin envperl use strict use warnings if 1,2 3 eq 1,2 3,else rightif 1.3 eq 1 2,3 else wrongif 1.1 2.2 3.3 1,2 3 else wrong my three 3 if 1,2,thr...