有人可以解释一下这句话中发生了什么吗?

时间:2020-01-14 20:15:05

标签: c dynamic-memory-allocation

我基本上理解指针。但是,当涉及到还涉及指针的矩阵的动态分配时,我在过程中迷路了。我想知道如何翻译这段代码才能理解它。

(*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,依此类推...但是我不能自然地在脑海中解释它,以便了解其中正在发生什么。

4 个答案:

答案 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],可从输入流中进行设置。