[英]Can someone explain me what is going on in this statement?
基本上我理解指針。 但是當涉及到也涉及指針的矩陣的動態分配時,我在這個過程中迷失了方向。 我想知道如何翻譯這段代碼才能理解它。
(*a)[i] = (int*)malloc((*m) * sizeof(int));
讀取矩陣的函數如下所示:
void reading(int *n, int *m, int ***a) {
int i, j;
printf("n=");
scanf("%d", &*n);
printf("m=");
scanf("%d", &*m);
(*a) = (int**)malloc((*n) * sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
}
還有聲明中***a
是什么意思。 我在大學時被告知,第一個星號代表動態分配,另外兩個代表涉及矩陣的事實。 對於向量動態分配是**v
等等......但我無法在腦海中自然地解釋它以了解其中發生的事情。
首先讓我回答你關於這條特定線路的問題:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
這樣做是分配一個正好包含*m
整數的數組,並將指向它的指針保存到指向int
的指針數組*a
,該數組之前分配為:
(*a) = (int**)malloc((*n) * sizeof(int*));
現在,如果仍然不清楚發生了什么,以更有意義的方式重新編寫代碼會有所幫助。 為了使事情更容易,您可以使用臨時變量來工作,並將值分配給僅在函數末尾作為參數傳遞的指針。 使用更有意義的名稱也有很大幫助。
void read_matrix(int *rows, int *columns, int ***matrix) {
int i, j, r, c;
int **mat;
printf("n = ");
scanf("%d", &r);
printf("m = ");
scanf("%d", &c);
// Allocate space for a matrix (i.e. an array of r integer pointers).
mat = malloc(r * sizeof(int*));
// Allocate space for each row of the matrix (i.e. r arrays of c integers).
for (i = 0; i < r; i++)
mat[i] = malloc(c * sizeof(int));
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("a[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
}
*rows = r;
*columns = c;
*matrix = mat;
}
由於我們現在將值的賦值移到函數末尾的參數中,我們擺脫了所有煩人的指針取消引用運算符 ( *
),代碼看起來更清晰。
您可以看到以前是:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
現在變成了:
mat[i] = malloc(c * sizeof(int));
這更容易理解。 這是為包含c
整數的數組(矩陣的一行)分配空間。
以前是:
(*a) = (int**)malloc((*n) * sizeof(int*));
現在變成了:
mat = malloc(r * sizeof(int*));
這是分配一個包含r
整數指針的數組(這意味着一個包含r
行的矩陣,如果每個指針指向一行)。
你沒有展示這個函數是如何調用的,但大概它看起來像這樣:
int n, m;
int **matrix;
reading(&n, &m, &matrix);
所以在這種情況下, matrix
被定義為一個指針到指針。 它可以保存一個int *
數組的第一個元素的地址,每個元素都可以保存一個int
數組的第一個元素的地址。
當&matrix
隨后被傳遞給這個函數,你有一個指針到指針到指針,這是什么說法a
的reading
是。 在這種情況下, a
包含一個指向單個int **
的指針,特別是調用函數中的matrix
。 通過在reading
取消引用a
,您實際上是在調用函數中訪問matrix
。
所以現在進入這一行:
(*a) = (int**)malloc((*n) * sizeof(int*));
這為*n
int *
數組分配空間並將其分配給*a
,(即調用函數中的matrix
。所以現在你有一個int *
數組。現在:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
這會遍歷int *
數組的元素,並為每個元素分配一個指向*m
int
足夠大的內存塊的指針。
因此,您現在有效地擁有了一個二維數組int
。 但是請注意,這與實際的二維int
數組不同,后者將被聲明為int arr[n][m]
。
首先,你在一個函數中做了太多不同的事情,這讓它有點混亂。 我建議您將獲取矩陣大小的邏輯與創建矩陣的邏輯分開:
void get_size(int *n, int *m) {
printf("n=");
scanf("%d", n);
printf("m=");
scanf("%d", m);
}
int **create_matrix(int n, int m) {
int **matrix = malloc(n * sizeof(int*));
for (int i = 0; i < n; i++)
matrix[i] = malloc(m * sizeof(int));
return matrix;
}
void fill_matrix(int **matrix, int n, int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", [i][j]);
}
}
}
從這里可以更容易地看到正在發生的事情, *
s 和&
s 更少。
你的矩陣被實現為一個數組數組,所以int **matrix = malloc(n * sizeof(int*));
為外部數組分配內存,而matrix[i] = malloc(m * sizeof(int));
為每個內部數組分配內存。
int ***a
聲明a
指向指向int
的指針的指針。 調用者需要擁有自己的int **
並將其地址傳遞給此函數。 例如,調用者可能定義int **x;
並將&x
傳遞給此函數以獲取參數a
。 我將使用x
來指代調用者的int **
。
(*a) = (int**)malloc((*n) * sizeof(int*));
將調用者的指針 ( x
) 設置為指向*n
指向int
指針的空間。 這是為構建*n
行矩陣做准備——將為每一行分配內存,我們將有一個指向該內存的指針,因此我們需要n
指針。
然后這些行:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
為*n
行分配內存。 第二行為m
int
數組分配內存並將x[i]
為指向該內存的第一個元素。 請注意,由於a
是int ***
, *a
是int **
,而(*a)[i]
是int *
。 因此, *a
指向一個int *
元素的數組。
最后,這些行:
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
設置*n
by *m
數組的每個元素:對於每個元素x[i][j]
(稱為(*a)[i][j]
,它傳遞元素的地址( &(*a)[i][j])
到要從輸入流設置的scanf
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.