c語言編程學習之二維數組
二維數組
c語言按照行主序存儲二維數組。也就是說,二維數組元素在記憶體中的位置是連續的,每行末尾元素(若不是最後一行)的下一個元素就是下一行的首元素。
如下圖所示
接下來我們來分析一下如何將二維數組所有元素初始化零。
假設數組的聲明如下:
int a[NUM_ROWS][NUM_COLS];
普通的寫法是利用兩層for循環
int row, col;
for (row = 0; row < NUM_ROWS; row++)
for (col = 0; col < NUM_COLS; col++)
a[row][col] = 0;
我們可以利用指針操作,將二維數組看成一個一維的大數組,其元素數量為NUM_ROWS*NUM_COLS,利用一個for循環完成操作
int *p;
for (p = &a[0][0]; p <= &a[NUM_ROWS-1][NUM_COLS-1]; p++)
*p = 0;
不過雖然程式碼量減少了,但實際上程式運行的次數和前者兩層for循環操作運行次數是一樣的。(這類方法明顯破壞了程式的可讀性,但是至少對一些老的編譯器來說這種方法在效率方面進行了補償。不過,對許多現代的編譯器來說,這樣所獲得的速度優勢往往極少甚至完全沒有。)
接下來我們再看一個例子:將二維數組第i行的元素置0
為了訪問到第i行的元素,讓p指向數組a中第i行的第一個元素:
p=&a[i][0];
實際上,我們還可以將這句程式碼簡寫為
p=a[i];
對於任意一維數組a[]來說,其首元素地址為a。而二維數組可以看成是多個一維數組,行數就是一維數組的個數,列數就是數組中元素的個數。由此第i行的首元素地址就為a[i]。
如果要正經推導的話:對於任意數組a來說,表達式a[i]等價於(a + i)。因此&a[i][0]等同於&((a[i] + 0)),而後者等價於&a[i];又因為&和運算符可以抵消,也就等同於a[i]。
那麼程式碼為:
int a[NUM_ROWS][NUM_COLS], *p, i;
for (p = a[i]; p < a[i] + NUM_COLS; p++)
*p = 0;
接下來我們再來思考一下怎麼將數組a的第i列的元素置零呢?
我們可以利用數組指針(指向數組的指針)來實現這點。如聲明一個數組指針:int (*p)[NUM_COLS]
。
我們知道,c語言指針每次自增1時,記憶體地址增加的量即為指針指向類型的所佔記憶體單元數。在這裡,p指向一個元素個數為NUM_COLS的int型數組,那麼p++將會導致p指向地址增加NUM_COLS*(int型所佔地址單元個數),這就實現了p從這一行指向了下一行。
程式碼如下
for(p = &a[0]; p < &a[NUM_ROWS]; p++){
(*p)[i] = 0;
}
最後,如果我們想遍歷整個數組的話,也可以將整個二維數組看成一整個一維數組,利用指針進行遍歷。
int *t;
for(t = a[0]; t <= &a[NUM_ROWS-1][NUM_COLS-1]; t++)
printf("%d ",*t);