天天看點

指針 多元數組 數組指針 指針數組

之前對數組的概念一直沒有了解透徹,隻覺得數組名就是個常量指針而已,用法和基本的指針差不多。是以當我嘗試用二級指針去通路二維數組時,就經常會出錯。下面就是剛開始寫的一個錯誤的程式:

開始的時候我是這樣分析的:本來數組和指針就差不多,一維數組和一維指針對應,那麼二維數組名應該和二維指針差不多,是以上面那個程式是沒有錯的,應該打 印出的是1和6。但是當我實際編譯運作的時候,卻出現了段錯誤,也就是我通路了不該通路的位址空間。那錯誤到底出在什麼地方呢?正确的程式應該怎麼寫呢?

為了解決問題,不得不讓我重新了解數組的含義。仔細翻閱一些書籍後,我發現其實數組并不是我原來想象的那麼簡單:一個常量指針辨別的一群變量的集合。數組 應該也算是一個完備的變量類型:有名字,有大小,也有位址。隻不多就是名字和它的位址一樣罷了。也正是因為數組有大小,是以當用sizeof對數組名進行 運算時,算出來的是實際數組的大小,而不是指針的大小。

也正是因為這樣,是以指向數組的指針和指向指針的指針也大不一樣。它們倆最明顯的不同就是表現在指針步進的時候。我們知道指針在進行++運算的時候,跨越 的實際位址取決于指針指向的資料類型:對于一般的32位機來說,假如指向的是int型資料,跨越的實際位址就是4,指向的是指針型資料,跨越的實際位址也 是4,當指向的是數組類型的時候,跨越的實際位址就是數組的長度了。

現在再回頭分析上面那個錯誤程式,根據下标引用符号[]的運算規則,我們知道parray[0][0]其實就是**parray,而iarray實際上隻 是個數組變量名,而它的值就是整個數組的開始位址(其實&iarray,iarray,iarray[0]以及&iarray的值都是數 組的開始位址,都是在編譯過程中編譯器賦予的值)。那麼其實*parray就已經是iarray[0][0]的值了,也就是1,而**parray則是去 通路位址為1的位址空間中的資料,自然會出段錯誤。

其實用指針通路二維數組可以直接用一級指針就可以了。比如下面這個程式:

    因為數組本身在位址空間中就是連續排列的,根據行數和列數,我們自己計算出通路單元的位址偏移量就可以用一級指針輕松周遊二維數組中的所有資料了。

我們還可以嘗試用指向數組的指針來通路二維數組的成員。下面就是事例程式:

簡單分析一下這個程式:我們知道[]運算符的結合方向是由左向右,parray[1][2]就等價于(* (parray + 1))[2],而由于parray是數組指針,而且數組的長度為3,是以* (parray + 1)就表示iarray[1]這個數組,則parray[1][2]則就完全等價于iarray[1][2]。

如果非得想用二級指針來通路二維數組的話,我們還得借用指針數組(數組記憶體儲的都是指針類型的資料),下面是事例程式:

由于二級指針要跳兩次,是以中間還需要額外的存儲一級指針的空間。是以一般不建議用二級指針去通路二維數組。