[英]What does double pointer mean and malloc of size of pointer date type
int **matrix, i, j;
matrix = malloc(5 * sizeof(int*));
*matrix = malloc(20 * sizeof(int));
我只是不了解雙指針的概念以及它如何轉換為二維數組(也就是說,它是真的)。謝謝。
從技術上講,這里創建的不是2D數組而是指針數組,每個指針都包含數組的起始地址。 然后可以將其索引為“真實” 2D數組。
這行代碼創建了一個由5個指向int
指針的數組:
matrix = malloc(5 * sizeof(int*));
下一行創建一個單個數組20 int
:
*matrix = malloc(20 * sizeof(int));
但是,這在2D數組方面是不完整的,因為僅分配了一行。 您需要遍歷matrix
指向的每個元素以創建每一行:
int **matrix, i;
matrix = malloc(5 * sizeof(int*));
for (i=0; i<5; i++) {
matrix[i] = malloc(20 * sizeof(int));
}
使用完此動態2D數組后,您需要按相反的順序釋放內存:
for (i=0; i<5; i++) {
free(matrix[i]);
}
free(matrix);
這與真實的2D陣列在某些方面有所不同。 首先,在真正的2D數組中,所有元素在內存中都是連續的,在這種情況下,指針數組和每個行數組都不是。
另一個區別是,傳遞給函數時,傳遞傳遞的方式與傳遞真實2D數組的傳遞方式不同。
對於簡單的一維數組,無論是在編譯時分配還是動態分配:
int a1[5];
int *a2 = malloc(5 * sizeof(int));
兩者都可以傳遞給這樣的函數:
void f(int *a);
但是對於2D數組:
int a[5][20];
它需要傳遞給這樣的函數:
void f(int a[5][20]);
或等效地:
void f(int (*a)[20]);
而動態2D數組需要傳遞給這樣的函數:
void f(int **a);
一些圖片可能會有所幫助。
讓我們從matrix
開始,它是一個指向int
指針:
int **
+--------+
| matrix |---???
+--------+
在第一次調用malloc
,您將擁有以下內容:
int ** int *
+--------+ +-----------+
| matrix |--->| matrix[0] |
+--------+ +-----------+
| matrix[1] |
+-----------+
| matrix[2] |
+-----------+
| matrix[3] |
+-----------+
| matrix[4] |
+-----------+
您已經為5個int *
對象動態分配了空間,並且matrix
指向第一個。 在第二次調用malloc
,您有了這個(表達式*matrix
等效於matrix[0]
-有關下面的更多內容):
int ** int * int
+--------+ +-----------+ +---------------+
| matrix |--->| matrix[0] |--->| matrix[0][0] |
+--------+ +-----------+ +---------------+
| matrix[1] | | matrix[0][1] |
+-----------+ +---------------+
| matrix[2] | | matrix[0][2] |
+-----------+ +---------------+
| matrix[3] | ...
+-----------+ +---------------+
| matrix[4] | | matrix[0][19] |
+-----------+ +---------------+
您已經為20個int
對象動態分配了空間,並且matrix[0]
指向第一個對象。
因此,簡而言之,每個matrix[i][j]
是一個int
。 每個matrix[i]
指向matrix[i][0]
,因此每個matrix[i]
必須是一個指向int
或int *
的指針。 matrix
指向matrix[0]
,這意味着matrix
必須是int *
或int **
的指針。
請記住,數組下標表達式a[i]
定義為*(a + i)
-給定地址a
,從該地址偏移i
元素 (不是字節!),並尊重結果。 因此, *matrix
等效於*(matrix + 0)
,等效於matrix[0]
。
現在,這里沒有一個真正的2D數組-您有一個指針序列,每個指針都可能指向一個int
對象序列的第一個(或根本沒有指向)。 陣列的“行”在內存中將很可能不相鄰。 在真正的2D數組中,所有數組元素都是連續的。 給定
int matrix[5][20];
元素將如下所示:
+---------------+
| matrix[0][0] |
+---------------+
| matrix[0][1] |
+---------------+
...
+---------------+
| matrix[0][19] |
+---------------+
| matrix[1][0] |
+---------------+
| matrix[1][1] |
+---------------+
...
+---------------+
| matrix[4][19] |
+---------------+
編輯
指針到指針和2D數組之間的其他一些關鍵區別。 首先,假設以下定義:
int **ptr;
int matrix[ROWS][COLS];
表達式ptr
類型為int **
。 表達式matrix
將從int [ROWS][COLS]
類型“衰減”到int (*)[COLS]
(指向COLS
int
元素數組的指針);
sizeof ptr
給出指針本身的大小(4、8或其他一些字節數)。 sizeof matrix
以字節為單位給出整個數組的大小( ROW * COLS * sizeof (int)
)。
表達式&matrix
, matrix
, &matrix[0]
和&matrix[0][0]
都將產生相同的值 (數組第一個元素的地址),盡管表達式的類型將不同int (*)[ROWS][COLS]
, int (*)[COLS]
, int (*)[COLS]
和int *
。 表達式&ptr
, ptr
, &ptr[0]
和&ptr[0][0]
都不會產生相同的值- &ptr
和&ptr[0][0]
值將不同於ptr
和&ptr[0]
,並且表達式的類型為int ***
, int **
, int **
和int *
。
我認為您需要以下條件:
int **matrix, i, j;
matrix = malloc(5 * sizeof(int*));
for (int i=0; i<5; i++)
matrix[i] = malloc(20 * sizeof(int));
在這里,您首先分配一個指向行的指針數組。 然后,您為每一行分配內存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.