前言
本文將探討一下關於二維數組在內存中的存儲和二維數組在參數傳遞時的使用。
一、二維數組在內存中的存儲
如果定義一個這樣的二維數組int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};則其在內存中的表示可能下面這樣的。
由上圖可以看出,在內存中二維數組是按照行主序進行存儲的,從內存的角度上看,二維數組本質就是一個一維數組。如果把二維數組的每一行看成一個整體,即看成一個數組中的一個元素,那么整個二維數組就是一個一維數組。而二維數組的名字代表二維數組第0行的首地址(注意它是代表一行元素的首地址,而不是第0行第0列元素的首地址,雖然是相等的,但不能這么理解,所以在沒有強制轉換的情況下,二維數據要么通過行指針進行參數傳遞,要么通過二維指針進行參數傳遞)。
二、二維數組在參數傳遞時的使用
1、 可以用二維數組名作為實參或者形參,在被調用函數中對形參數組定義時可以指定所有維數的大小,也可以省略第一維的大小說明,如:
void Func(int array[3][10]);
void Func(int array[][10]);
但是不能把第二維或者更高維的大小省略,如下面的定義是不合法的:
如 void Func(int array[3][]);
因為從實參傳遞來的是數組的起始地址,在內存中按數組排列規則存放(行主序),而並不區分行和列,如果在形參中不說明列數,則系統無法決定應為多少行,多少列,不能只指定一維而不指定第二維。
2、將二維數組作為指針進行參數傳遞
(1)直接作為行指針(數組指針)來傳遞參數(二維數組的名字代表二維數組第0行的首地址)
1 #include "stdafx.h" 2 #include<iostream> 3 using namespace std; 4 5 void test(int (*a)[4],int m,int n) 6 { 7 cout<<*(*(a+m)+n); 8 } 9 10 int _tmain(int argc, _TCHAR* argv[]) 11 { 12 int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; 13 test(a,1,1); 14 return 0; 15 }
上述程序中int (*a)[4],可以理解為二維數組的行指針(這個指針指向二維數組的行,而每一行最多有4列),a[n]表示二維數組的第n行,所以cout<<*(*(a+m)+n);先定位出a數組的第m行的位置,然后再求出第m行第n列的值
(2)參數傳遞時將二維數組的強制轉換為一維指針,然后按照內存中存儲的方法計算二維數組對應成一維數組的下標
1 #include "stdafx.h" 2 #include<iostream> 3 using namespace std; 4 void test(int *a,int row,int column,int m,int n) 5 { 6 cout<<a[m*column+n]; 7 } 8 9 int _tmain(int argc, _TCHAR* argv[]) 10 { 11 int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; 12 test((int*)a,3,4,1,1); 13 return 0; 14 }
注意參數傳遞時將二維數組的強制轉換為一維指針,如上述程序中的第12行
注意:切不可將二維數組直接轉換成二維指針作為形參傳遞,因為在這樣子函數中不知道每一個一維元素含有多少個二維元素。
如,下面這樣寫就是錯誤的:
#include<iostream> using namespace std; void test(int **a,int m,int n) { cout<<*(*(a+m)+n); } int main() { int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; test((int **)a,1,1); return 0; }