如何在函数中使用 realloc 创建动态结构数组

How to create dynamic array of structs using realloc in function

我正在尝试使用 realloc 创建结构的动态数组(在本例中为图片)。我想在函数中这样做,但是有一个问题:main 中的变量不会被这个函数改变。指针一定有问题,但我找不到它。 PS: 函数 UploadFile 工作正常。 有一个函数:

int AddPicture(struct Picture ***tab, int *PicCounter)
{
    struct Picture *temp;
    struct Picture pic;
    (*PicCounter)++;
    temp = realloc(*tab, (*PicCounter) *sizeof(*temp));
    if (temp != NULL)
    {
        UploadFile(&pic);
        **tab = temp;
        (*tab)[*PicCounter-1]->name = pic.name;
        (*tab)[*PicCounter-1]->type[0] = pic.type[0];
        (*tab)[*PicCounter-1]->type[1] = pic.type[1];
        (*tab)[*PicCounter-1]->width = pic.width;
        (*tab)[*PicCounter-1]->height = pic.height;
        (*tab)[*PicCounter-1]->scale = pic.scale;
        (*tab)[*PicCounter-1]->table = pic.table;
    }
    else {
        printf("Memory reallocation error");
        free(temp);
        return 1;
    }
return 0;
}

我是这样称呼它的:

struct Picture *tabofpics;
int piccounter = 0;
tabofpics = malloc(1 * sizeof(*tabofpics));
AddPicture(&tabofpics,&piccounter);

感谢您的帮助。

编辑: 我试过 **tab 而不是 ***tab 并且 main 中的值是正确的,但它的行为就像内存没有正确重新分配,即使 realloc 没有 return NULL。

  int AddPicture(struct Picture **tab, int *PicCounter)
{
    struct Picture *temp;
    struct Picture pic;
    (*PicCounter)++;
    temp = realloc(*tab, (*PicCounter) * sizeof(*temp));
    if (temp != NULL)
    {
    UploadFile(&pic);
    *tab = temp;    
    tab[*PicCounter - 1]->name = pic.name;
    tab[*PicCounter - 1]->type[0] = pic.type[0];
    tab[*PicCounter - 1]->type[1] = pic.type[1];
    tab[*PicCounter - 1]->width = pic.width;
    tab[*PicCounter - 1]->height = pic.height;
    tab[*PicCounter - 1]->scale = pic.scale;
    tab[*PicCounter - 1]->table = pic.table;
}
else {
    printf("Memory reallocation error");
    free(*tab);
    return 1;
}
return 0;
}                                                                                                                             

这个想法是在程序中放多少张图片就放多少张,对其进行一些操作然后离开。必须有添加和删除图片的功能,只要用户想要,但是当我第二次在参数中使用 **tab 调用函数时,我得到了访问冲突位置,所以正如我之前提到的,realloc 一定不能正常工作。

在我看来,您需要改进代码的逻辑,例如

  1. 还不递增 PicCounter
  2. 您的指针间接级别不匹配,在调用函数中您有 struct Picture * 并且您将其作为 struct Picture ** 传递给采用 struct Picture *** 的函数。您应该对此进行推理,以及您真正想要的是什么。看来你想要一个 struct Picture *.
  3. 的数组

风格,

  1. 不要使用 PicCounter 作为变量,使用 number_of_pictures 或更合适的东西。
  2. 不要写1 * sizeof(...)它太露骨了,你不需要那么多。

工具,

  1. 启用编译器警告以发现您在没有注意到的情况下犯下的简单错误,或者那些概念上的错误,例如代码中指针的间接寻址不匹配。

也就是说,我想你可能想写这个

int
AddPicture(struct Picture ***tab, int *counter)
{
    struct Picture **array;   
    array = realloc(*tab, (*counter + 1) * sizeof(*array));
    if (array != NULL)
    {
        struct Picture *current;
        // We will avoid using the `tab' variable because it's
        // confusing, the only reason why it's a *** pointer is
        // to do this here, and below where we set it to `NULL'
        *tab = array;
        // We also need to allocate space for a new image to store
        // the results in.
        current = malloc(sizeof(*current));
        if (current == NULL)
            goto error;    
        // This is a guess, but isn't the code just initializing
        // the `pic' that you allocated on the stack?
        //
        // Well, the following is the same.
        //
        // Oh, and should we check for errors here?
        UploadFile(current);            
        // Now we can increase counterand update our array
        array[(*counter)++] = current;
        // We have succeded, so return 0
        return 0;
    }
error:
    printf("Memory reallocation error");
    // Release memory allocated so far
    free(*tab);
    // Prevent dangling pointer
    *counter = 0;
    *tab = NULL;
    // A non zero value means, an error
    return 1;
}

调用函数应该是这样的

struct Picture **tabofpics;
int counter = 0;
// `realloc' will take car of the allocation
tabofpics = NULL;
if (AddPicture(&tabofpics, &picounter) == 0)
    // Everything ok, picture added
else
    // Error

请小心 *** 指针,它们会引起很多混乱。我要考虑四五次

(*tab)[*counter] = current;

在我看到它是正确的之前。所以我选择更改它,如您在代码中看到的那样。

您的代码应尽可能具有描述性,使用 *** 指针会导致错误的方向。

您的代码中的以下两个摘录或许可以最好地概括核心问题:

    temp = realloc(*tab, (*PicCounter) *sizeof(*temp));

[...]

        **tab = temp;

您正在重新分配由 *tab 的值指向的 space,但成功后,您将指向新 space 的指针存储在 **tab 中,这是一个不同的位置。不管哪一个是指针的正确位置,组合肯定是错误的。

然而,事实上,考虑到您调用函数的方式...

struct Picture *tabofpics;

[...]

AddPicture(&tabofpics,&piccounter);

...实参的类型是struct Picture **。这适合您的目的,因此您应该调整函数定义以匹配:

int AddPicture(struct Picture **tab, int *PicCounter)

。此外,您应该确保头文件中存在匹配的函数声明,该头文件 #included 进入包含 AddPicture 定义的源文件以及包含对该函数的调用的每个源文件。再加上确保出现编译器警告,编译器应该能够帮助您诊断此函数的定义和使用之间的不匹配。

完成后,函数 AddPicture() 中的表达式 *tab 将引用表达式 tabofpics(无 *)在 main()。这似乎与您实际使用它的方式一致,但我在开头描述的不匹配除外。

可以对您的代码提出其他合理的批评,但@Iharob 已经在他的回答中很好地解决了这些问题。

根据@Iharob 和@John 的回答,我能够编写一个工作函数:

 int AddPicture(struct Picture **tab, int *PicCounter)
{
struct Picture *temp;
(*PicCounter)++;
temp = realloc(*tab, (*PicCounter) * sizeof(*temp));
if (temp != NULL)
{
    struct Picture *pic;
    pic = malloc(sizeof(*pic));
    UploadFile(pic);
    *tab = temp;
    (*tab)[(*PicCounter)-1] = *pic;
    free(pic);
}
else {
    printf("Memory reallocation error");
    free(*tab);
    (*PicCounter)--;
    return 1;
}
return 0;
}

它并不完美,但可以正常工作。感谢您的帮助!