简体   繁体   English

当你有一个指向结构指针的指针时,如何使用realloc?

[英]How do you use realloc when you have a pointer to a pointer of a struct?

I have this array of structs and this function takes a pointer to the pointer of the array. 我有这个结构数组,这个函数接受一个指向数组指针的指针。 The original size is 2, so whenever it reaches the size, I need to realloc and double the size. 原始大小为2,所以每当达到大小时,我需要重新分配并加倍大小。 When this code runs, I get an invalid old size error from the realloc. 当这段代码运行时,我从realloc中得到一个无效的旧大小错误。 What am I doing wrong? 我究竟做错了什么?

  int PopulateArray(struct Inventory **inv, int *size, FILE *inputFile) {
    int count = 0;
    printf("address: %u\n", inv);
    printf("address: %u\n", **inv);
    int itemNumber;
    int quantity;
    float price;
    int month;
    int year;
    while (fscanf(inputFile, "%i %i %f %i/%i", &itemNumber,
    &quantity, &price, &month, &year) != EOF) {
      (*inv)->itemNumber = itemNumber;
      (*inv)->quantity = quantity;
      (*inv)->price = price;
      (*inv)->expDate.month = month;
      (*inv)->expDate.year = year;
      printf("count: %i  size: %i\n", count, *size);

      if (count == *size - 1) {
        inv = realloc(inv, (*size * 2 * sizeof(struct Inventory)));
        *size *= 2;
      }
      inv++;
      count++;
    }
    return count;
  }

In your function, inv is (presumably) the address of a pointer variable. 在你的函数中, inv (推测)是指针变量的地址。 Its the value of that variable you want to pass to realloc . 它是您要传递给realloc变量的值。

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory)));

For the same reason, incrementing inv itself won't do what you expect. 出于同样的原因,递增inv本身不会达到预期效果。

Because you need to use realloc , you should use count to reference the array. 因为您需要使用realloc ,所以应该使用count来引用数组。

while (fscanf(inputFile, "%i %i %f %i/%i", &itemNumber,
    &quantity, &price, &month, &year) != EOF) {
  (*inv)[count].itemNumber = itemNumber;
  (*inv)[count].quantity = quantity;
  (*inv)[count].price = price;
  (*inv)[count].expDate.month = month;
  (*inv)[count].expDate.year = year;
  printf("count: %i  size: %i\n", count, *size);

  if (count == *size - 1) {
    *inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory)));
    if (*inv == NULL) {
        perror("realloc failed");
        exit(1);
    }
    *size *= 2;
  }
  count++;
}

The problem occurs because you're modifying inv ( inv++; ). 出现此问题是因为您正在修改invinv++; )。

You can only realloc data if the passed pointer is a valid allocated pointer, not a pointer within the allocated zone. 您只能realloc如果传递的指针是有效分配的指针,而不是分配给区域的数据指针,

So you have to store your inv data so you can use realloc . 因此,您必须存储您的inv数据,以便您可以使用realloc Pointer on the current element must be a different variable. 当前元素上的指针必须是不同的变量。

And check that realloc doesn't return NULL before assigning back to inv or you'll lose your original pointer. 并且在分配回inv之前检查realloc是否返回NULL ,否则您将丢失原始指针。

That almost made me miss the biggest mistake (1 mistake hiding the other, classical): you're passing a struct Inventory ** type so you can modify the pointer, but you're modifying the double pointer instead. 这几乎让我错过了最大的错误(1个错误隐藏了另一个错误,经典):你传递的是一个struct Inventory **类型,所以你可以修改指针,但你要修改双指针。

You should perform your realloc on the pointed value, not on the address of the pointer: 您应该在指向的值上执行realloc,而不是在指针的地址上执行:

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory)));

When you update inv from realloc() , your inv now points to the start of the newly resized array. 当您从realloc()更新inv ,您的inv现在指向新调整大小的数组的开头 So, your code 所以,你的代码

  if (count == *size - 1) {
    inv = realloc(inv, (*size * 2 * sizeof(struct Inventory*)));
    *size *= 2;
  }
  inv++;

the last inv++ will make inv point effectively to inv[1] , not the inv[count] which you would probably wanted to point to. 最后一个inv++会使inv点有效地成为inv[1] ,而不是你可能想要指向的inv[count]

I am adding below because incorrect answers are being upvoted 我在下面添加,因为错误的答案正在被投票

The suggestion of 的建议

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory)));

is not correct. 是不正确的。

What you are attempting to do is doubling the array of pointers dynamically. 你试图做的是动态地加倍指针数组。 So the correct pointer type to pass to realloc here is struct Inventory ** . 因此,传递给realloc的正确指针类型是struct Inventory **

(You probably created initial table by pptr = malloc(sizeof(struct Inventory*) * INIT_SIZE) , so inv is correct type for realloc here) (你可能通过pptr = malloc(sizeof(struct Inventory*) * INIT_SIZE)创建了初始表,所以invrealloc正确类型)

Having said that, after you performing the realloc in your function, the original inv pointer used by the code that called this function is no longer valid, so upon returning this function, you lose your pointer to the resized array. 话虽如此,在您的函数中执行realloc之后,调用函数的代码使用的原始inv指针不再有效,因此在返回此函数时,您将丢失指向调整大小的数组的指针。 To deal with this, you have to return the new inv pointer value to the calling function. 要处理这个问题,您必须将新的inv指针值返回给调用函数。

additional edit: 额外编辑:

And don't forget to allocate memory for the actual struct Inventory item: 并且不要忘记为实际的struct Inventory项目分配内存:

inv[count] = malloc(sizeof(struct Inventory));

at the start of the loop. 在循环的开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM