简体   繁体   English

在 function 中重新分配和操作二维数组

[英]Reallocing and manipulating a 2d-array inside a function

I am trying to reallocate both elements of a 2D-array and also manipulate the values in the 2D-array within the same function. But I just can't seem to get it to work.我正在尝试重新分配二维数组的两个元素,并在同一个 function 中操作二维数组中的值。但我似乎无法让它工作。 On compiling the code doesn't show any errors, but when running it will only ever print the amount of lines I specified as the initial_size at the beginning of the main function.在编译代码时没有显示任何错误,但在运行时它只会打印我在main function 开头指定为initial_size的行数。

So it seems that the inner realloc is working fine, as it always prints an entire row once it gets started.所以看起来内部realloc工作正常,因为它总是在启动后打印一整行。 But the outer realloc is not working, as it will only print a couple of rows.但是外部realloc不起作用,因为它只会打印几行。

Note: The real code takes input of unknown size, from getchar() / scanf() .注意:实际代码从getchar() / scanf()获取未知大小的输入。 That is why the realloc functions are inside loops in the function.这就是为什么realloc函数在 function 中的循环内部。

Simplified version of the function, with error handling omitted: function 的简化版本,省略了错误处理:

void func(int ***A) {
    int i, j;
    int len = 2;
    int len2 = 2;
    
    for (i = 0; i < 10; i++) {
        // Check to see if a realloc is needed.
        if (i >= len) {
            len *= 2;
            int **tmp = realloc(*A, len * sizeof(int*));
            *A = tmp;
            printf("Len1 = %d\n", len);
        }
        len2 = 2;
    
        for (j = 0; j < 20; j++) {
            // Check to see if a realloc is needed.
            if (j >= len2) {
                len2 *= 2;
                int *new_row = realloc((*A)[i], len2 * sizeof(int));
    
                (*A)[i] = new_row;
            }
            // Assign value.
            (*A)[i][j] = i * j;
        }
    }
}

int main() {
    int i, j;
    int initial_size = 2;
    int **A;
 
    // Malloc with a starting size of 2 (could be any size).
    A = malloc(initial_size * sizeof(int*));
    for (i = 0; i < initial_size; i++) {
        A[i] = malloc(initial_size * sizeof(int));
    }

    // Call function.
    func(&A);

    // Print the results, row by row.
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 20; j++) {
            printf("%d, ", A[i][j]);
        }
        printf("\n");
    }
    return 0;
}

I have been stuck for a while now, so any help is greatly appreciated:)我已经被困了一段时间了,所以非常感谢任何帮助:)

When you realloc in the outer loop, you increase the numbers of pointers from two (those created in main ) to four.当您realloc循环中重新分配时,指针的数量从两个(在main中创建的)增加到四个。

The value of the two pointers from main are copied to the new memory area.来自main的两个指针的值被复制到新的 memory 区域。

The value of the two new pointers are indeterminate and that's your problem.两个新指针的值是不确定的,这是你的问题。 You never initialize them by allocating memory - yet you use them in the other loop.您永远不会通过分配 memory 来初始化它们 - 但您会在另一个循环中使用它们。

Further, it seems that you realloc the inner array dimensions individually but you only track one length (ie len2 ).此外,您似乎单独realloc了内部数组维度,但您只跟踪一个长度(即len2 )。 That's also a problem.这也是一个问题。

And the line len2 = 2 between the loops are wrong as you loose information about previously allocated memory.循环之间的行len2 = 2是错误的,因为您丢失了有关先前分配的 memory 的信息。

There are multiple problems in your code:您的代码中存在多个问题:

  • you reallocate the pointer array but do not initialize the pointers in the newly allocated portion您重新分配指针数组但不初始化新分配部分中的指针
  • you only reallocate the first int array pointed to by the pointer array您只重新分配指针数组指向的第一个int数组
  • you do not initialize the newly allocated area in this int array.您没有初始化此int数组中新分配的区域。

Note that 2D-matrices are more idiomatic in C as arrays of arrays, but it is difficult to manipulate such arrays when the outer dimension is not fixed at compile time.请注意,二维矩阵在 C 中更符合 arrays 中的 arrays,但是当外部维度在编译时不固定时,很难操作这样的 arrays。

You should use a reallocation function with specified dimensions for the current and target sizes and deal with reallocating and freeing the blocks appropriately.您应该为当前和目标大小使用指定尺寸的重新分配 function,并适当地处理重新分配和释放块。 Also avoid triple pointers: just return the potentially reallocated outer array.还要避免三重指针:只返回可能重新分配的外部数组。

#include <stdio.h>
#include <stdlib.h>

int **func(int **A, int rows, int cols, int new_rows, int new_cols) {
    int i, j;

    /* free the rows that are discarded */
    if (new_rows < rows) {
        for (i = new_rows; i < rows; i++) {
            free(A[i]);
        }
    }
    /* free the outer array if new rows is zero */
    if (new_rows == 0) {
        free(A);
        return NULL;
    }
    /* reallocate the outer array if required */
    if (new_rows != rows) {
        A = realloc(A, sizeof(*A) * new_rows);
    }
    /* reallocate the existing rows */
    if (new_cols != cols) {
        for (i = 0; i < rows; i++) {
            A[i] = realloc(A[i], sizeof(int) * new_cols);
            if (new_cols > cols) {
                for (j = cols; j < new_cols; j++)
                    A[i][j] = 0;
            }
        }
    }
    /* allocate the new rows (initialized to 0) */
    for (i = rows; i < new_rows; i++) {
        A[i] = calloc(sizeof(int), new_cols);
    }
    return A;
}

int main() {
    int **A = NULL;

    /* reallocate to 10x20 */
    A = func(A, 0, 0, 10, 20);

    // Print the results, row by row.
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 20; j++) {
            printf("%d, ", A[i][j]);
        }
        printf("\n");
    }
    /* reallocate to 0x0 (free the matrix) */
    func(A, 10, 20, 0, 0);
    return 0;
}

Note that the above code does not check for memory allocation failure.请注意,上面的代码不会检查 memory 分配失败。 To deal with this possibility, it would be much simpler to allocate a new array and copy the current values, then free the previous matrix if no allocation error occurred.为了处理这种可能性,分配一个新数组并复制当前值,然后在没有发生分配错误的情况下释放先前的矩阵会简单得多。 It would also be more efficient to allocate all rows as a single block of memory. Below is an example of this approach:将所有行分配为 memory 的单个块也会更有效。下面是这种方法的示例:

#include <stdio.h>
#include <stdlib.h>

int **func(int **A, int rows, int cols, int new_rows, int new_cols) {
    int i, j;
    int **B = NULL;

    if (new_rows == rows && new_cols == cols)
        return A;

    if (new_rows != 0 && new_cols != 0) {
        /* allocate the new matrix */
        B = malloc(sizeof(*B) * new_rows);
        if (B == NULL)
            return NULL;
        B[0] = calloc(sizeof(int) * new_cols, new_rows);
        if (B[0] == NULL) {
            free(B);
            return NULL;
        }
        /* initialize the row pointers */
        for (i = 1; i < new_rows; i++) {
            B[i] = B[i - 1] + new_cols;
        }
        /* copy the current data */
        for (i = 0; i < new_rows && i < rows; i++) {
            for (j = 0; j < new_cols && j < cols; i++) {
                B[i][j] = A[i][j];
            }
        }
    }

    /* free the previous matrix */
    if (A != NULL) {
        free(A[0]);
        free(A);
    }
    return B;
}

int main() {
    int **A = NULL;
    int i, j;

    /* reallocate to 10x20 */
    A = func(A, 0, 0, 10, 20);
    if (A == NULL) {
        printf("Matrix reallocation failed\n");
        return 1;
    }

    // Print the results, row by row.
    for (i = 0; i < 10; i++) {
        for (j = 0; j < 20; j++) {
            printf("%d, ", A[i][j]);
        }
        printf("\n");
    }
    /* reallocate to 0x0 (free the matrix) */
    func(A, 10, 20, 0, 0);
    return 0;
}

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

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