用指標的形式傳遞二維陣列
後記假設我打算建立乙個二維陣列,並建立乙個指標用於儲存這個二維陣列的位址,對於如下兩種方法,
int arr[2]
[3]=
;int
**ptr = arr;
int arr[2]
[3]=
;int
(*ptr)[3
]= arr;
使用第一種方法時,編譯器會報錯如下:int (*)[3] 型指標不能賦給 int ** 型指標
,這是因為對於建立的二維陣列arr[2][3],當編譯器去編譯int arr[2][3]
指令的時候,記憶體中實際的分配情況如下:
由於arr是陣列下標int
型陣列,每個記憶體塊的大小為 4個位元組假設
arr[0][0]
的位址為1000
,那麼對於arr[0][i]
,當i加1時,位址也會相應增加 4個位元組,也就是1004
由此類推:
實際位址
陣列下標
實際位址
陣列下標
實際位址
arr[0][0]
1000
arr[0][1]
1004
arr[0][2]
1008
arr[1][0]
1012
arr[1][1]
1016
arr[1][2]
1020
同時,對於arr[2][3]
,可以理解為含有兩個各包含了三個int
元素的一維陣列的陣列, 這樣看來:
arr[0]
實際上代表著這個二維陣列中所儲存的第乙個一維陣列;
arr[1]
實際上代表著這個二維陣列中所儲存的第二個一維陣列。
若是按著這個思路繼續理解下去,arr[0]
代表著乙個一維陣列,而arr[0][i]
又可以從這個陣列中取值,那麼是不是可以這樣理解:arr[0]
為乙個指向這個一維陣列的指標呢?如下的**可以對這個猜想進行驗證:
#include
intmain()
;int
*ptr_0 = arr[0]
;//建立乙個指向第乙個一維陣列的指標
//測試輸出
for(
int i =
0; i <
3; i++
)return0;
}
可以看到輸出的內容為
即第乙個陣列內的三個元素均被正確地輸出了,至此,我們可以得知arr[i]
實際上是乙個int
型指標,它的每次步進都會使其在記憶體中的位置移動 4個位元組。
那麼,進一步地思考,如果arr[i]
是乙個指向arr[i][0]
位置的int
型指標,而arr[i]
又是存放在arr
這個陣列中的值,於是可以推測arr
即是指向arr[0]
位置的指標。
把上面的猜想聯絡起來可以得到arr
是乙個指向指標的指標,於是我們自然而然地就會想到arr
應該是int **
型的值,但回到開頭的**示例,這個想法顯然是錯誤的,這是不妨思考乙個問題,如果arr
是int **
型值,那麼當我對arr
進行一次自增運算之後,它應該指向**呢?
顯然,我們並不能知道它該指向**,因為我們只是定義了arr,而沒有告知每一次步進所需要移動的記憶體長度
而事實上,每一次步進需要移動的記憶體長度為3 * sizeof(int),即整乙個一維陣列的記憶體長度,於是我們可以這樣告訴編譯器:
int arr[2]
[3]=
;int
(*ptr)[3
]= arr;
在這樣的操作下,我們就用int (*ptr)[3] = arr
這個式子告訴了編譯器,ptr
是乙個指標,它指向的是含有三個int
型元素的一維陣列。
#include
#include
intmain()
//刪除動態二維陣列
for(
int i =
0; i < line; i++
)free
(arr)
;return0;
}
這裡就出現了和上文不一樣的現象:arr
變成了int **
型,為什麼呢?這要從**中的記憶體分配步驟來看:
首先,定義了int **arr
用malloc函式開闢了儲存兩個int *
型值的記憶體,並將這個記憶體的位址以int **
型值賦給arr
用malloc函式開闢儲存三個int
型值的記憶體,重複兩次,分別將記憶體的位址以int *
型值賦給arr[0]
、arr[1]
也就是說,arr[0]
和arr[1]
是連續的,它們都是儲存int *
型別的值的記憶體,而指標arr
又被定義為int **
型, 因此對於arr
來說,arr + 1
可以正確地指向arr[1]
。
同時,又因為每個一維陣列都是通過呼叫一次malloc函式來分配的,因此它們的記憶體同樣也是連續的,通過*arr
得到arr[0][0]
的位址,對*arr
進行步進,同樣也能得到預期值。
簡略地介紹如何通過指標的形式傳遞固定長度陣列和動態陣列
對於固定長度陣列,通過前文的介紹,需要告訴被調函式它所接收指標的步進長度(即一維陣列的長度),**例項如下:
#include
intsum
(int(*
)[2]
,int);
intmain()
;printf
("%d"
,sum
(arr,3)
);return0;
}int
sum(
int(
*arr)[2
],int line)
}return sum;
}
這是乙個簡單地將陣列內所有元素加和的函式,我們可以看到,在主調函式內傳遞時不需要宣告指標的型別,而在被調函式接收時則需要具體表明arr
是int (*)[2]
型別。
下面,同樣用這個例子來展示動態陣列的呼叫:
#include
#include
intsum
(int**
,int
,int);
intmain()
printf
("%d"
,sum
(arr, line, column));
//刪除動態二維陣列
for(
int i =
0; i < line; i++
)free
(arr)
;return0;
}int
sum(
int*
* arr,
int line,
int column)
}return sum;
}
與固定長度陣列不同的是,由於被調函式無法得知陣列的列數,因此還需要多傳遞乙個列數的引數。
第一次寫csdn的部落格,希望有錯誤的話能幫忙指正一下哈!
三連給乙個好嗎xdm
二維陣列的指標及其指標變數
1 二維陣列的指標 有定義語句 int a 3 4 從二維陣列角度看,陣列名a 代表陣列的起始位址,是乙個以行為單位進行控制的行指標,由一維陣列構成的一維陣列就是二維陣列,a i 是行指標值,指向二維陣列的第i 行。a i 是列指標值,指向第i 行第0 列。a i 陣列元素a i 0 的值。用a 作...
c 二維陣列指標
定義指標指向二維陣列 為了方便根據使用者輸入動態定義二維陣列的行和列,引入變數rowsnum 行 colsnum 列 以定義 行 列的二維陣列為例,int rowsnum 4 int colsnum 5 float a new float rowsnum for int i 0 i rowsnum ...
C 二維陣列指標
概括的說,指標其實就是可變陣列的首位址,說是可變陣列,是 指其包含內容的數量的可變的,並且是可動態申請和釋放的,從而充 分節約寶貴的記憶體資源。我一向喜歡一維陣列,除非萬不得已,我一 般是不用二維陣列的,多維的則更是很少涉足了。因為一維簡單,容 易理解,而用指標指向的多維陣列就具有相當的複雜性了,也...