简体   繁体   English

有人可以解释一下这个声明中发生了什么吗?

[英]Can someone explain me what is going on in this statement?

Basically i understand pointers.基本上我理解指针。 But when it comes to dynamic allocation for matrices which also involve pointers, i'm getting lost in the process.但是当涉及到也涉及指针的矩阵的动态分配时,我在这个过程中迷失了方向。 I wanna know how can i translate this segment of code in order to understand it.我想知道如何翻译这段代码才能理解它。

(*a)[i] = (int*)malloc((*m) * sizeof(int));

The function for reading the matrix looks like this:读取矩阵的函数如下所示:

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]);
        }
    }
}

And also what is the meaning of ***a in the declaration.还有声明中***a是什么意思。 I was told at college that te first asterisk stands for dynamic allocation and the other two's from the fact that is a matrix involved.我在大学时被告知,第一个星号代表动态分配,另外两个代表涉及矩阵的事实。 For vectors dynamic allocation is **v and so on... but i can't naturally explain it in my mind in order understand what is happening in it.对于向量动态分配是**v等等......但我无法在脑海中自然地解释它以了解其中发生的事情。

First let me answer your question about this specific line:首先让我回答你关于这条特定线路的问题:

(*a)[i] = (int*)malloc((*m) * sizeof(int));

What this is doing is allocating an array of exactly *m integers and saving a pointer to it into the array *a of pointers to int , which was previously allocated as:这样做是分配一个正好包含*m整数的数组,并将指向它的指针保存到指向int的指针数组*a ,该数组之前分配为:

(*a) = (int**)malloc((*n) * sizeof(int*));

Now, if it still isn't clear what is going on, re-writing the code in a more meaningful way will help.现在,如果仍然不清楚发生了什么,以更有意义的方式重新编写代码会有所帮助。 To make things easier, you can use temporary variables to work, and assign the values to the pointers passed as arguments only at the end of the function.为了使事情更容易,您可以使用临时变量来工作,并将值分配给仅在函数末尾作为参数传递的指针。 Using more meaningful names also helps a lot.使用更有意义的名称也有很大帮助。

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;
}

Since we now moved the assignment of the values to the arguments at the end of the function, we got rid of all the annoying pointer dereference operators ( * ), and the code looks way cleaner.由于我们现在将值的赋值移到函数末尾的参数中,我们摆脱了所有烦人的指针取消引用运算符 ( * ),代码看起来更清晰。

You can see that what previously was:您可以看到以前是:

(*a)[i] = (int*)malloc((*m) * sizeof(int));

now became:现在变成了:

mat[i] = malloc(c * sizeof(int));

Which is much easier to understand.这更容易理解。 This is allocating space for an array (a row of the matrix) holding c integers.这是为包含c整数的数组(矩阵的一行)分配空间。

What previously was:以前是:

(*a) = (int**)malloc((*n) * sizeof(int*));

now became:现在变成了:

mat = malloc(r * sizeof(int*));

This is allocating an array of r integer pointers (which means a matrix of r rows, if each pointer points to a row).这是分配一个包含r整数指针的数组(这意味着一个包含r行的矩阵,如果每个指针指向一行)。

You don't show how this function is called, but presumably it looks something like this:你没有展示这个函数是如何调用的,但大概它看起来像这样:

int n, m;
int **matrix;
reading(&n, &m, &matrix);

So in this context, matrix is defined as a pointer-to-pointer.所以在这种情况下, matrix被定义为一个指针到指针。 It can hold the address of the first element of an array of int * , each of which can hold the address of the first element of an array of int .它可以保存一个int *数组的第一个元素的地址,每个元素都可以保存一个int数组的第一个元素的地址。

When &matrix is then passed to this function, you have a pointer-to-pointer-to-pointer, which is what the argument a of reading is.&matrix随后被传递给这个函数,你有一个指针到指针到指针,这是什么说法areading是。 In this context, a contains a pointer to a single int ** , specifically matrix in the calling function.在这种情况下, a包含一个指向单个int **的指针,特别是调用函数中的matrix By dereferecing a in reading , you're actually accessing matrix in the calling function.通过在reading取消引用a ,您实际上是在调用函数中访问matrix

So now getting to this line:所以现在进入这一行:

(*a) = (int**)malloc((*n) * sizeof(int*));

This allocates space for an array of *n int * and assigns that to *a , (ie matrix in the calling funtion. So now you have an array of int * . Now for this:这为*n int *数组分配空间并将其分配给*a ,(即调用函数中的matrix 。所以现在你有一个int *数组。现在:

for (i = 0; i < *n; i++)                     
    (*a)[i] = (int*)malloc((*m) * sizeof(int)); 

This loops through the elements of the int * array and assigns to each one a pointer to a memory block big enough for *m int .这会遍历int *数组的元素,并为每个元素分配一个指向*m int足够大的内存块的指针。

So you now effectively have a 2D array of int .因此,您现在有效地拥有了一个二维数组int Note however that this is not the same as an actual 2D array of int which would be declared as int arr[n][m] .但是请注意,这与实际的二维int数组不同,后者将被声明为int arr[n][m]

First, you are doing too many different things in a single function, which is making it a bit messy.首先,你在一个函数中做了太多不同的事情,这让它有点混乱。 I suggest that you separate out the logic to get the matrix size from the logic to create the matrix:我建议您将获取矩阵大小的逻辑与创建矩阵的逻辑分开:

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]);
        }
    }
}

From here it is a lot easier to see what is going on, with fewer * s and & s.从这里可以更容易地看到正在发生的事情, * s 和& s 更少。

Your matrix is implemented as an array of arrays, so int **matrix = malloc(n * sizeof(int*));你的矩阵被实现为一个数组数组,所以int **matrix = malloc(n * sizeof(int*)); allocates memory for the outer array, while matrix[i] = malloc(m * sizeof(int));为外部数组分配内存,而matrix[i] = malloc(m * sizeof(int)); allocates memory for each of the inner arrays.为每个内部数组分配内存。

int ***a declares a to be a pointer to a pointer to pointer to an int . int ***a声明a指向指向int的指针的指针。 The caller is required to have their own int ** and to pass its address to this function.调用者需要拥有自己的int **并将其地址传递给此函数。 For example, the caller might define int **x;例如,调用者可能定义int **x; and pass &x to this function for the parameter a .并将&x传递给此函数以获取参数a I will use x to refer to the caller's int ** .我将使用x来指代调用者的int **

(*a) = (int**)malloc((*n) * sizeof(int*)); sets the caller's pointer ( x ) to point to space for *n pointers to int .将调用者的指针 ( x ) 设置为指向*n指向int指针的空间。 This is preparation for fabricating a matrix of *n rows—memory will be allocated for each row, and we will have a pointer to that memory, so we need n pointers.这是为构建*n行矩阵做准备——将为每一行分配内存,我们将有一个指向该内存的指针,因此我们需要n指针。

Then these lines:然后这些行:

for (i = 0; i < *n; i++)                     
    (*a)[i] = (int*)malloc((*m) * sizeof(int));

allocate memory for *n rows.*n行分配内存。 The second line allocates memory for an array of m int and sets x[i] to point to the first element of that memory.第二行为m int数组分配内存并将x[i]为指向该内存的第一个元素。 Note that since a is an int *** , *a is an int ** , and (*a)[i] is an int * .请注意,由于aint ****aint ** ,而(*a)[i]int * Thus, *a points to an array of int * elements.因此, *a指向一个int *元素的数组。

Finally, these lines:最后,这些行:

for (i = 0; i < *n; i++) {
    for (j = 0; j < *m; j++) {
        printf("a[%d][%d]=", i, j);
        scanf("%d", &(*a)[i][j]);
    }
}

set each element of the *n by *m array: For each element x[i][j] (referred to as (*a)[i][j] , it passes the address of the element ( &(*a)[i][j]) to scanf to be set from the input stream.设置*n by *m数组的每个元素:对于每个元素x[i][j] (称为(*a)[i][j] ,它传递元素的地址( &(*a)[i][j])到要从输入流设置的scanf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM