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

时间:2018-12-23 14:00:09

标签: c arrays struct realloc

我正在尝试使用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;
}

在main中有这样的称呼:

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

感谢帮助。

编辑: 我尝试了** tab而不是*** tab,并且main中的值是正确的,但它的行为就像内存无法正确重新分配,即使realloc不会返回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调用函数时,我获得了访问冲突位置,因此,如前所述,重新分配不能正常工作。

3 个答案:

答案 0 :(得分:2)

可以从代码中的以下两个摘录中最好地概括出中心问题:

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

[...]

        **tab = temp;

您正在重新分配*tab值所指向的空间,但是成功后,您将指向新空间的指针存储在**tab中,是另一个位置< / em>。不管其中哪一个是指针的正确位置,组合肯定是错误的。

实际上,考虑到调用函数的方式...

struct Picture *tabofpics;
     

[...]

AddPicture(&tabofpics,&piccounter);

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

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

。此外,您应确保在#include头文件中存在匹配的函数声明,该头文件AddPicture到包含*tab的定义的源文件中,并在每个包含对该函数调用的源文件中。这样,再加上确保出现编译器警告,应该可以使编译器有能力帮助您诊断该功能的定义与使用之间的不匹配。

这样做,函数AddPicture()中的表达式tabofpics将引用与{{1}中的表达式*(无main())所引用的对象}。这似乎与您实际使用它的方式一致,除了我一开始所描述的不匹配。

可以对您的代码进行其他合理的批评,但是@Iharob已经很好地解决了他的回答。

答案 1 :(得分:1)

例如,您需要改进代码的逻辑

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

样式

  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

请注意***指针,它们可能会引起很多混乱。我必须考虑4到5次

(*tab)[*counter] = current;

在我看到它是正确的之前。因此,如您在代码中所见,我选择对其进行更改。

您的代码应尽可能地具有描述性,并且使用***指针会朝错误的方向发展。

答案 2 :(得分:-1)

根据@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;
}

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