程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 深入淺出C指針(三)多維數組

深入淺出C指針(三)多維數組

編輯:關於C語言

1.概念
如果某個數組的維數不止1個,它就被稱為多維數組。例如,下面這個聲明:
int matrix[6][10];
創建了一個包含60個元素的矩陣。但是,它是6行每行10個元素,還是10行每行6個元素?
為了回答這個問題,你需要從一個不同的觀點視察多維數組。考慮下列這些維數不斷增加的聲明:
int a;
int b[10];
int c[6][10];
int d[3][6][10];
a和b很好理解。c只是在b的基礎上在增加一維,所以我們把c看作是一個包含6個元素的向量,只不過他的每個元素本身又是一個包含10個元素的向量。換句話說,c是一個一維數組的一維數組。d也是如此:它本身是一個含有3個元素的向量,而這三個元素中每個元素本身又是一個含有6個元素的向量,而這6個元素各自本身又是一個含有10個元素的向量。


2.存儲順序
請記住,多維數組只是表示上的一種寫法,而在實際的內存空間存儲中,還是按照順序的存儲方式。
例如:int[2][5];
在內存中是按順序排列的10個小區域。
看看下面這個例子:
int matrix[6][10];
int *mp;
.....
mp = &matrix[3][8]
printf("First value is %d\n",*mp);
printf("Second value is %d\n",*++mp);
printf("Third value is %d\n",*++mp);
很顯然,第一個被打印的值將是matrix[3][8]的內容,那下一個被打印的又是什麼?順序存儲可以回答這個問題--下一個元素將是最右邊下標首先變化的那個,也就是matrix[3][9]。再接下去又輪到誰呢?第9列已是最後一列。不過,按順序存儲的規定,一行存滿後就輪到下一行,所以下一個被打印的元素將是matrix[4][0]。


2.數組名
一維數組的數組名是一個指針常量,這一點大家應該已經十分清楚了。它的類型是“指向元素類型的指針”,它指向數組元素的第一個元素。多維數組也差不多,但是這個“差不多”往往會給初學者帶來一定的誤導,多維數組的數組名,也是一個指針,這個指針指向的是該數組的第一個“元素”,這個“元素”也是一個數組。例如,下面這個聲明:
int matrix[3][10];
接著看以下的表達式:
matrix[1][5]
這個很簡單,該表達式表示這個數組的第二行,第六列所包含的元素。
matrix + 1
如果你認為這個表達式指向了第一行的第二個元素,那麼你就錯了。實際上,這個表達式指向的是第二行整個數組,而不是任何一個元素。www.2cto.com
而*(matrix + 1)是一個指向第二行第一個元素的指針。*(*(matrix + 1))表示了第二行第一個元素的具體值。
其實就筆者感覺,C語言多維數組這樣的設計方式不是十分恰當,這樣做和一維數組的規則沒有十分緊密的聯系起來,就易於理解而言,matrix + 1表示第一行的第二個元素更為容易理解一些。不過可能是出於編碼的簡潔性考慮,C語言的發明人采用了這樣“自動換行”的處理過程。
小提示:
在許多其他的語言,比如大家熟悉的C#中,多重下標被寫成用逗號分割的形式。比如:
matrix[3,4];
如果你在C語言中這樣寫會發生什麼呢?你的第一感覺一定是:編譯錯誤。不過很可惜,C語言可以讓這樣的表達式編譯通過(還記得2[array]嗎?C語言的靈活性是其他語言所不能比擬的)。
這樣看上去沒有什麼問題,實際這樣的表達式運行結果一定會和你預想的結果不一樣。
C語言的逗號表達式會將其轉換成matrix[3]。
如果編譯器可以發現這個錯誤還好,可惜由於逗號表達式的存在,編譯器無法發現這樣的錯誤。
3.指向數組的指針
下面這些聲明合法嗎?
int  vector[10], *vp = vector;
int  matrix[3][10], *mp = matrix;
第一個聲明是合法的。它為一個整形數組分配內存,並把vp聲明成一個指向整形的指針,並把它初始化指向vector數組的第一個元素。
第二個聲明是非法的。它正確的創建了matrix數組,並把mp聲明為一個指向整形的指針。但是,mp的初始化是不正確的,因為matrix並不是一個指向整形的指針,而是一個指向整形數組的指針。我們應該怎樣聲明一個指向整形數組的指針呢?
int (*p)[10];
這個聲明略微復雜但卻是正確的,在聲明中加上初始化後是下面這個樣子:
int  (*p)[10] = matrix;
它使p指向matrix的第一行。
p是一個指向擁有10個整形元素的數組指針。當你把p與一個整數相加時,該整數首先根據10個整形的長度進行調整,然後再進行加法。所以我們可以使用這個指針一行一行地在matrix中移動。
如果你需要的是一個指針逐個訪問整形元素而不是逐行在數組中移動,我們可以這樣聲明:
int *pi = &matrix[0][0];
int *pi = matrxi[0];


4.初始化
對多維數組的初始化,一般有兩種方式:
int matrix[2][3] = {100,101,102,103,104,105};
int matrix[2][3] = {
           {100,101,102},
           {103,104,105}
         };
二者在本質上沒有任何區別,只是第二種初始化的方式程序可讀性更高一些。
 


摘自 Kernel & UI 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved