天天看點

二維數組指針

 概括的說,指針其實就是可變數組的首位址,說是可變數組,是

指其包含内容的數量的可變的,并且是可動态申請和釋放的,進而充

分節約寶貴的記憶體資源。我一向喜歡一維數組,除非萬不得已,我一

般是不用二維數組的,多元的則更是很少涉足了。因為一維簡單,容

易了解,而用指針指向的多元數組就具有相當的複雜性了,也是以更

具有讨論的必要。

    閑話少說,這裡我就以三個二維數組的比較來展開讨論:

    (1)、int **Ptr;

    (2)、int *Ptr[ 5 ];

    (3)、int ( *Ptr )[ 5 ];

    以上三例都是整數的二維數組,都可以用形如 Ptr[ 1 ][ 1 ] 的

方式通路其内容;但它們的差别卻是很大的。下面我從四個方面對它們

進行讨論:

    一、内容:

       它們本身都是指針,它們的最終内容都是整數。注意我這裡說

的是最終内容,而不是中間内容,比如你寫 Ptr[ 0 ],對于三者來說,

其内容都是一個整數指針,即 int *;Ptr[ 1 ][ 1  ] 這樣的形式才

是其最終内容。

    二、意義:

       (1)、int **Ptr 表示指向"一群"指向整數的指針的指針。

       (2)、int *Ptr[ 5 ] 表示指向 5 個指向整數的指針的指針。

       (3)、int ( *Ptr )[ 5 ] 表示指向"一群"指向 5 個整數數

組的指針的指針。

    三、所占空間:

       (1)、int **Ptr 和 (3)、int ( *Ptr )[ 5 ] 一樣,在32位平

台裡,都是4位元組,即一個指針。

       但 (2)、int *Ptr[ 5 ] 不同,它是 5 個指針,它占5 * 4 = 20

個位元組的記憶體空間。

    四、用法:

       (1)、int **Ptr 

       因為是指針的指針,需要兩次記憶體配置設定才能使用其最終内容。首

先,Ptr = ( int ** )new int *[ 5 ];這樣配置設定好了以後,它和(2)的

意義相同了;然後要分别對 5 個指針進行記憶體配置設定,例如:

  Ptr[ 0 ] = new int[ 20 ];

  它表示為第 0 個指針配置設定 20 個整數,配置設定好以後, Ptr[ 0 ] 為指

向 20 個整數的數組。這時可以使用下标用法 Ptr[ 0 ][ 0 ] 到

Ptr[ 0 ][ 19 ] 了。

      如果沒有第一次記憶體配置設定,該 Ptr 是個"野"指針,是不能使用

的,如果沒有第二次記憶體配置設定,則 Ptr[ 0 ] 等也是個"野"指針,也

是不能用的。當然,用它指向某個已經定義的位址則是允許的,那是另外

的用法(類似于"借雞生蛋"的做法),這裡不作讨論(下同)。

      (2)、int *Ptr[ 5 ]

      這樣定義的話,編譯器已經為它配置設定了 5 個指針的空間,這相當

于(1)中的第一次記憶體配置設定。根據對(1)的讨論可知,顯然要對其進行一次

記憶體配置設定的。否則就是"野"指針。

      (3)、int ( *Ptr )[ 5 ]

      這種定義我覺得很費解,不是不懂,而是覺得了解起來特别吃力,

也許是我不太習慣這樣的定義吧。怎麼描述它呢?它的意義是"一群"

指針,每個指針都是指向一個 5 個整數的數組。如果想配置設定 k 個指針,

這樣寫: Ptr = ( int ( * )[ 5 ] ) new int[ sizeof( int ) * 5 * k ]。

這是一次性的記憶體配置設定。配置設定好以後,Ptr 指向一片連續的位址空間,

其中 Ptr[ 0 ] 指向第 0 個 5 個整數數組的首位址,Ptr[ 1 ] 指向第

1 個 5 個整數數組的首位址。

   綜上所述,我覺得可以這樣了解它們:

   int ** Ptr <==> int Ptr[ x ][ y ];

   int *Ptr[ 5 ] <==> int Ptr[ 5 ][ x ];

   int ( *Ptr )[ 5 ] <==> int Ptr[ x ][ 5 ];

   這裡 x 和 y 是表示若幹的意思。