我基本上理解指针。但是,当涉及到还涉及指针的矩阵的动态分配时,我在过程中迷路了。我想知道如何翻译这段代码才能理解它。
(*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
,依此类推...但是我不能自然地在脑海中解释它,以便了解其中正在发生什么。
答案 0 :(得分:1)
首先让我回答您有关此特定行的问题:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
这是在分配正好为*m
的整数数组,并将指向它的指针保存到指向*a
的指针数组int
中,该指针先前分配为:>
(*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
行的矩阵)。
答案 1 :(得分:0)
您没有显示此函数的调用方式,但大概看起来像这样:
int n, m;
int **matrix;
reading(&n, &m, &matrix);
因此在 this 上下文中,matrix
被定义为指针到指针。它可以保存int *
数组的第一个元素的地址,每个元素可以保存int
数组的第一个元素的地址。
然后将&matrix
传递给此函数时,您将拥有一个指向指针的指针,这就是a
的参数reading
的含义。在这种情况下,a
包含指向单个int **
,特别是调用函数中的matrix
的指针。通过在a
中取消引用reading
,您实际上是在调用函数中访问matrix
。
现在进入这一行:
(*a) = (int**)malloc((*n) * sizeof(int*));
这将为*n
int *
的数组分配空间,并将其分配给*a
,(即调用函数中的matrix
。所以现在您有了{ {1}}。为此:
int *
这循环遍历for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
数组的元素,并为每个指针分配一个指向足以容纳int *
*m
的存储块的指针。
因此,您现在实际上拥有int
的2D数组。但是请注意,这与int
的实际2D数组不同,后者将被声明为int
。
答案 2 :(得分:0)
首先,您在一个函数中做了太多不同的事情,这使它有些混乱。我建议您从逻辑中分离出用于获取矩阵大小的逻辑以创建矩阵:
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]);
}
}
}
从这里开始,使用更少的*
和&
来查看正在发生的事情要容易得多。
您的矩阵实现为数组数组,因此
int **matrix = malloc(n * sizeof(int*));
为外部数组分配内存,而
matrix[i] = malloc(m * sizeof(int));
为每个内部数组分配内存。
答案 3 :(得分:0)
int ***a
声明a
是指向int
的指针的指针。要求调用者拥有自己的int **
并将其地址传递给此函数。例如,调用者可以定义int **x;
并将&x
传递给参数a
的函数。我将使用x
来指代呼叫者的int **
。
(*a) = (int**)malloc((*n) * sizeof(int*));
设置调用者的指针(x
)指向指向*n
的{{1}}指针的空间。这是制造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
的每个元素:对于每个元素*m
(称为x[i][j]
,它传递元素的地址({{1 }}至(*a)[i][j]
,可从输入流中进行设置。