【问题标题】:realloc a 2d-array with a void function in c在 c 中重新分配具有 void 函数的二维数组
【发布时间】:2020-12-20 23:27:13
【问题描述】:

我正在尝试从 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 **'

我做错了什么?

谢谢!

【问题讨论】:

  • 鉴于int **arr,你认为sizeof *arr是什么?
  • 请注意这不是realloc should be used
  • @AndrewHenle 我不喜欢使用“类型”,而是从变量中推断它来分配内存。类型可以稍后更改?请让我知道我是否对此有误以及如何改进。
  • @Bob__, *arr2 = realloc(arr, sizeof *arr * 2); ?
  • @aerijman 你没有回答我的问题。如果arrint ** 类型,*arr 是什么类型?当 sizeof 传递该类型时,sizeof 返回的是什么?

标签: c pointers void


【解决方案1】:
_"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。如果对realloc() 的调用失败,从而导致释放原始指针,则设置指针== NULL 提供了一种方法来测试稍后调用free(),从而避免调用的可能性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

【讨论】:

    猜你喜欢
    • 2021-03-11
    • 1970-01-01
    • 2012-03-27
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多