在 c 中重新分配一个带有 void 函数的二维数组

realloc a 2d-array with a void function in c

我正在尝试从 void 函数修改二维数组。

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


void try_by_reference(int **arr){
    *arr = realloc(*arr, sizeof *arr * 2);
}

int main(int argc, char **argv){
   
    // declare dynamic 2d-array and allocate memory
    int (*arr)[2] = malloc(sizeof *arr * 10);
   
    // fill array
    for (int i=0; i<10; i++){
        arr[i][0] = i;
        arr[i][1] = i+10;
   
    }

    // declare and fill a simpler dynamic array
    int *tarr = malloc(sizeof(int) * 10);
    for (int i=0; i<10; i++)
        tarr[i] = i*2;

    try_by_reference(&tarr);
    try_by_reference(&arr);          <-- this gets warning

    free(arr);
    free(tarr);

    return 0;
}

编译器说:

 warning: incompatible pointer types passing 'int (**)[2]' to parameter of type 'int **'

我做错了什么?

谢谢!

_"I am trying to modify a 2D array from a void function."_  

这里有一些提示和修复,可让您将内存更新为两个指向 int 的指针的数组。 (请参阅与您的代码一致的评论)

void try_by_reference(int **arr){
    //always use a temporary variable to call realloc, otherwise if failed attempt - memory leak will occur
    int *tmp = realloc(*arr, 2 * sizeof(*arr));//this effectively reduces memory from original 10, to 2 instances of int
    if(!tmp)//always check return of realloc, if it fails free original memory and return
    {
        free(*arr);
        //set pointer to NULL here to provide way to test before 
        //freeing later in process. (See 'Reference' below)
        *arr = NULL;//to prevent problems in subsequent free calls
        return;
    }
    else *arr = tmp;
}

int main(int argc, char **argv){
   
    // declare dynamic 2d-array and allocate memory
    int *arr[2] = {NULL, NULL};//this is an array of 2 pointers to int - each
                      //need to be allocated
                      //it will result in an array shaped as array[2][10]
                      //after following calls to malloc.
    arr[0] = malloc(10*sizeof(arr[0]));//original provides memory for 10 instances of int
    if(arr[0])
    {
        arr[1] = malloc(10*sizeof(arr[1]));
        if(arr[1])
        {
            // fill array
            //for (int i=0; i<10; i++){
            for (int i=0; i<10; i++){
                //arr[i][0] = i;
                //arr[i][1] = i+10;
                arr[0][i] = i;//switch indices 
                arr[1][i] = i+10;//switch indices
           
            }
        }
    }

    // declare and fill a simpler dynamic array
    int *tarr = malloc(sizeof(int) * 10);
    for (int i=0; i<10; i++)
        tarr[i] = i*2;

    try_by_reference(&tarr);
    
    //try_by_reference(&arr);          <-- this gets warning
    //pass address of each pointer to memory, one at a time
    try_by_reference(&(arr[0]));        
    try_by_reference(&(arr[1]));       

    //To prevent UB from calling free on an already freed pointer
    //test before calling free.  
    if(arr[0]) free(arr[0]);//need to free each of two pointers to memory
    if(arr[1] free(arr[1]);//...
    if(tarr) free(tarr);

    return 0;
}

关于 why set pointer to NULL after freeing. If the call to realloc() fails, thus resulting in freeing the original pointer, setting the pointer == NULL provides a way to test before calling free() later in process, thus avoiding the potential of invoking undefined behavior (UB) 的参考

有几种方法可以在 C 中创建不同形状的 nD 数组内存,其中一些比 int *arr[2] 更容易更新内存。但我仍然使用此表格来具体说明更新它的方法。虽然它需要更严格的访问元素,但对于由指针实现的 int[2][10],我更喜欢创建一个 int *arr = malloc(2*10*sizeof(*arr));。观察以下示例以进行易用性比较。 (使用 2D like,但尺寸不同):

int arr1[3][6] = {{1,2,3,4,5,6},{7,8,9,10,11,12},{13,14,15,16,17,18}};
//same memory as 
int arr2[18] = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}};

knowing that   *(arr1 + 2*6 + 5) == arr2[2][5] = 18;
               *(arr1 + 0*6 + 4) == arr2[0][4] = 5;
               *(arr1 + 1*6 + 0) == arr2[1][0] = 7;
//                      | |   |_2nd index range 0 - 5    
//                      | |_ constant -> sizeof(arr1[0]/arr1[0][0])
//                      |1st index range is from 0 - 2

The same is true for dynamic memory.  int **arr1 and *arr2

int **arr1 //requires 7 calls to malloc/free
int *arr2  //requires 1 call to malloc/free