指針訪問二維數組

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

複製代碼
#include <stdio.h>

int main()
{
        int iArray[2][3] =        {{1,2,3},{4,5,6}};
        int **pArray = NULL;

        pArray = iArray;
        
        printf("array[0][0] = %d\n", pArray[0][0]);
        printf("array[1][2] = %d\n", pArray[1][2]);
                
        return 0;
}
複製代碼
 

     開始的時候我是這樣分析的:本來數組和指針就差不多,一維數組和一維指針對應,那麼二維數組名應該和二維指針差不多,所以上面那個程序是沒有錯的,應該打印出的是1和6。但是當我實際編譯運行的時候,卻出現了段錯誤,也就是我訪問了不該訪問的地址空間。那錯誤到底出在什麼地方呢?正確的程序應該怎麼寫呢?
     爲了解決問題,不得不讓我重新理解數組的含義。仔細翻閱一些書籍後,我發現其實數組並不是我原來想象的那麼簡單:一個常量指針標識的一羣變量的集合。數組應該也算是一個完備的變量類型:有名字,有大小,也有地址。只不多就是名字和它的地址一樣罷了。也正是因爲數組有大小,所以當用sizeof對數組名進行運算時,算出來的是實際數組的大小,而不是指針的大小。
     也正是因爲這樣,所以指向數組的指針和指向指針的指針也大不一樣。它們倆最明顯的不同就是表現在指針步進的時候。我們知道指針在進行++運算的時候,跨越的實際地址取決於指針指向的數據類型:對於一般的32位機來說,假如指向的是int型數據,跨越的實際地址就是4,指向的是指針型數據,跨越的實際地址也是4,當指向的是數組類型的時候,跨越的實際地址就是數組的長度了。
     現在再回頭分析上面那個錯誤程序,根據下標引用符號[]的運算規則,我們知道pArray[0][0]其實就是**pArray,而iArray實際上只是個數組變量名,而它的值就是整個數組的開始地址(其實&iArray,iArray,iArray[0]以及&iArray的值都是數組的開始地址,都是在編譯過程中編譯器賦予的值)。那麼其實*pArray就已經是iArray[0][0]的值了,也就是1,而**pArray則是去訪問地址爲1的地址空間中的數據,自然會出段錯誤。
     其實用指針訪問二維數組可以直接用一級指針就可以了。比如下面這個程序:

複製代碼
int main()
{
        int iArray[2][3] =        {{1,2,3},{4,5,6}};
        int *pArray = NULL;

        pArray = iArray;
        
        printf("array[0][0] = %d\n", *pArray);
        printf("array[1][2] = %d\n", *(pArray + 1 * 3 + 2));
                
        return 0;
}
複製代碼
    因爲數組本身在地址空間中就是連續排列的,根據行數和列數,我們自己計算出訪問單元的地址偏移量就可以用一級指針輕鬆遍歷二維數組中的所有數據了。
我們還可以嘗試用指向數組的指針來訪問二維數組的成員。下面就是事例程序:
複製代碼
int main()
{
        int iArray[2][3] =        {{1,2,3},{4,5,6}};
        int (*pArray)[3] = NULL;

        pArray = iArray;
        
        printf("array[0][0] = %d\n", pArray[0][0]);
        printf("array[1][2] = %d\n", pArray[1][2]);
                
        return 0;
}
複製代碼

     簡單分析一下這個程序:我們知道[]運算符的結合方向是由左向右,pArray[1][2]就等價於(* (pArray + 1))[2],而由於pArray是數組指針,而且數組的長度爲3,所以* (pArray + 1)就表示iArray[1]這個數組,則pArray[1][2]則就完全等價於iArray[1][2]。
     如果非得想用二級指針來訪問二維數組的話,我們還得借用指針數組(數組內存儲的都是指針類型的數據),下面是事例程序:

複製代碼
int main()
{
        int iArray[2][3] =        {{1,2,3},{4,5,6}};
        int *ipArray[2] = {iArray[0], iArray[1]};
        int **pArray = NULL;

        pArray = ipArray;
        
        printf("array[0][0] = %d\n", pArray[0][0]);
        printf("array[1][2] = %d\n", pArray[1][2]);
                
        return 0;
}
發佈了46 篇原創文章 · 獲贊 11 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章