二维指针数组的内存分配

3
我很困惑动态内存分配和删除2D指针数组。目标是创建一个2D数组,其中每个单元格都有指向链表的指针。这就是我的做法,我没有发现任何错误,但有一些警告。
警告:
1)
a value of type queue ** cannot be used to initialize an entity of type queue ***
queue* (**table) = (queue**)malloc(sizeof(queue*)*3);

2)
a value of type queue * cannot be assigned to an entity of type queue **
    table[indexI] = (queue*)malloc(sizeof(queue*)*3);

3)
a value of type queue ** cannot be assigned to an entity of type queue ***
  if( !(table = allocate()) ) {

以下是代码:
queue **allocate() {

    queue* (**table) = (queue**)malloc(sizeof(queue*)*3);
    // Warning #1 at above line 
    for(.....) {

    table[index] = (queue*)malloc(sizeof(queue*)*3);
    // Warning #2 at above line. 
    }

    for(I index - 0 to 3) {
    for(J index - 0 to 3) {

    table[I][J] = NULL;

    }
    }
    return((queue**)table);
   }

    void deallocate(queue* **table) {


    // will handle list deletion
    // next deallocate table

    for(....) {
    free(table[index]);
    }
    free(table);

   }

void
add_list_to_queue(queue ***table) {

// here I create a list of queue type and assign it to
// those cells

}

modify_table() {

    queue* (**table) = NULL;

    table = allocate();
// Warning #3 at above line
.
.
.
    add_list_to_queue(table);

// do de allocation of table, list etc.,

    deallocate(table);

}

我在以下几个方面感到困惑:

  1. 我不确定我的二维指针数组声明是否正确
  2. 如何传递这个二维指针数组

1
为什么不使用queue *(*arr)[COLUMNS] = malloc(sizeof(*arr) * ROWS); - user529758
队列 *(*arr)[COLUMNS] - 我认为列的内存将在堆栈上分配? - navoriion
@userXXX 当你(我)正在使用malloc()?绝不可能。 - user529758
@navoriion 然后你将拥有一个未初始化的变量,名为 arr,它是指向 queue 指针数组的指针。 - user529758
@H2CO3 我无法想象这个内存分配会是什么样子。你能否请发一些图表吗? - navoriion
显示剩余4条评论
2个回答

2
第一个警告是因为括号在您表达式的LHS中没有任何区别。
queue* (**table) = (queue**)malloc(sizeof(queue*)*3);

table只是一个指向队列的三级指针。但是malloc返回一个指向可以容纳三个指向队列的指针的内存块的指针,因此您正在分配一个指向队列的二级指针。

由于table是一个三级指针,table[indexI]是一个二级指针。但是在表达式的右侧,您不一致:

table[indexI] = (queue*)malloc(sizeof(queue*)*3);

malloc 再次返回一个指向可以容纳三个队列指针的内存块的指针(即malloc 返回一个二级指针),但您将其强制转换为一级指针,然后将其分配给一个二级指针。

至于第三个警告,您已将 allocate() 定义为返回指向队列指针的指针,但您试图将其分配给 table。如上所述,table 是一个三级指针,但 allocate() 仅返回一个二级指针。

但实际上,在这里不需要多级指针间接引用。保持简单。你需要什么?每行包含指向队列的指针的行指针。这就是H2CO3在他的评论中提供给您的建议:

queue *(*arr)[COLUMNS] = malloc(sizeof(*arr) * ROWS);

arr是指向一个由ROW组成的数组的指针,每个ROW包含COLUMNS个指向queue的指针。

编辑:如您在评论中所要求的那样将其传递给不同的函数,请先声明并初始化指针:

queue* (*arr) [COLUMNS] = NULL;

如果要分配内存,记得您需要更改指针所指向的内容。因此,您需要传递一个指向指针的指针。您的函数原型应该是:

void allocate (queue* (**arr) [COLUMNS]);  // Note the (**arr)

函数调用应该是:
allocate (&arr);

为了更加方便地进行指针间接引用,您可能希望在allocate()函数内声明和初始化一个不同的指向数组的指针,并使用我上面解释过H2CO3首先建议的格式,然后将该指针分配给* arr。请注意,您不仅要为指向2D数组的指针分配内存,还要为数组内的每个元素分配内存,因为该元素是未初始化的指针。您可以在allocate()中使用嵌套循环,或者如果按照数据结构更合乎逻辑,则在fill_table()中使用嵌套循环来实现这一点。
对于fill_table()函数,您只需传递指向数组本身的指针即可。原型将如下所示:
void fill_table (queue* (*arr) [COLUMNS]);

并且需要调用:

fill_table (arr);

希望这能帮到你。最简单的方法可能是一开始就在process()内完成所有操作,然后再看如何将分配和填充部分分离成自己的函数。


谢谢您的详细解答,那么我该如何释放这个队列的内存呢?arr)[COLUMNS] = malloc(sizeof(*arr) * ROWS); - navoriion
首先,您需要遍历数组并释放为每个队列分配的内存,使用嵌套循环:for (int i = 0; i < ROWS; i++) for (int j = 0; j < COLUMNS; j++) free(arr[i][j]);完成后,释放为整个数组分配的内存:free(*arr); - verbose
好的,我明白了。我该如何传递这个队列 *(*arr)[COLUMNS] 并返回它呢?所以,我有三个函数 process()、allocate 和 fill_table()。我在 process 中调用 allocate 和 fill_table。allocate 会为这个数组分配内存,然后将其发送到 fill_table(),以填充这个表格中的队列。我尝试以各种方式发送这个数组,但是我收到警告和错误,例如错误:表达式必须具有指向对象的指针类型,返回值类型与函数类型不匹配,类型为“queue *”的参数与类型为“queue ()[COL]”的参数不兼容。 - navoriion
我看到你之前的评论说我的上一个问题的答案太长了,那我应该开一个新的帖子来问这个问题吗? - navoriion
在StackOverflow上已经有很多关于如何在函数之间传递多维数组的问题,你可能需要在发帖前进行一些研究。如果你在阅读这些内容后仍有疑问,请确保提出尽可能具体的问题。我现在有点忙于其他事情,抱歉。 - verbose
这里有一个解决你问题的问题:http://stackoverflow.com/questions/4152837/passing-2d-array-of-pointer-to-function-c。 - verbose

0

1) 你的第一个错误 (queue* (**table)) 是你这里没有一个二维数组,而是一个三维数组,你的代码可以写成这样:queue ***table。所以,你只需要去掉一个星号,就可以声明一个二维数组指针。

2) 根据第一个回答,我认为你不会再有这个警告了。

3) 这个错误和第一个一样,你只需要去掉一个星号。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接