Как мне выделить больше места для моего массива структур C? - PullRequest
5 голосов
/ 01 ноября 2010

Я пытаюсь добавить еще 10 элементов в мою структуру, которая уже была malloc с фиксированным размером 20. Это способ, которым я определил свою структуру:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct st_temp {
   char *prod;
};

int main ()
{
   struct st_temp **temp_struct;

   size_t j;
   temp_struct = malloc (sizeof *temp_struct * 20);
   for (j = 0; j < 20; j++) {
      temp_struct[j] = malloc (sizeof *temp_struct[j]);
      temp_struct[j]->prod = "foo";
   }

   return 0;
}

Итак, что у меня былоимелось в виду перераспределить как (однако, не уверен, как это сделать):

temp_struct = (struct st_temp **) realloc (st_temp, 10 * sizeof(struct st_temp*));

, а затем добавить дополнительные 10 элементов,

   for (j = 0; j < 10; j++)
      temp_struct[j]->prod = "some extra values";

Как я мог этого добиться?Любая помощь приветствуется!

Ответы [ 2 ]

8 голосов
/ 01 ноября 2010

Когда вы используете realloc(), вы должны указать новый размер вместо количества байтов для добавления.Итак:

temp_struct = (struct st_temp **) realloc (temp_struct, 30 * sizeof(struct st_temp*));

30 - это, конечно, ваши исходные 20 плюс 10 больше.Функция realloc() заботится о копировании исходных данных в новое место, если необходимо переместить блок памяти.

Тогда добавление дополнительных 10 элементов будет выглядеть примерно так (начиная с индекса 20, а не с 0):

for (j = 20; j < 30; j++) {
    temp_struct[j]->prod = "some extra values"; 
}
6 голосов
/ 01 ноября 2010

Чтобы избежать утечек памяти, нам нужно аккуратно обращаться с перераспределением (подробнее об этом позже). Функция realloc:

void *realloc(void *ptr, size_t size), где

ptr = указатель на оригинальный (malloc 'ed) блок памяти и

size = новый размер блока памяти (в байтах).

realloc возвращает новое местоположение динамически выделенного блока памяти (который мог измениться) - или NULL, если перераспределение не удалось! Если возвращается NULL, исходная память остается неизменной, поэтому вы всегда должны использовать временную переменную для возвращаемого значения realloc.

Пример прояснит это немного (интересные факты: синтаксис realloc аналогичен синтаксису malloc (нет необходимости в дополнительных приведениях и т. Д.), И после realloc вам необходимо выполнить те же шаги для новых объектов, что и после таНос):

struct st_temp **temp_struct;
temp_struct = malloc(20 * sizeof *temp_struct);
if (temp_struct == NULL) { /* handle failed malloc */ }
for (int i = 0; i < 20; ++i) {
    temp_struct[i] = malloc(sizeof *temp_struct[i]);
    temp_struct[i]->prod = "foo";
}

// We need more space ... remember to use a temporary variable
struct st_temp **tmp;
tmp = realloc(temp_struct, 30 * sizeof *temp_struct);
if (tmp == NULL) { 
    // handle failed realloc, temp_struct is unchanged
} else {
    // everything went ok, update the original pointer (temp_struct)
    temp_struct = tmp; 
}
for (int i = 20; i < 30; ++i) { // notice the indexing, [20..30)
    // NOTICE: the realloc allocated more space for pointers
    // we still need to allocate space for each new object
    temp_struct[i] = malloc(sizeof *temp_struct[i]);
    temp_struct[i]->prod = "bar";
}
// temp_struct now "holds" 30 temp_struct objects
// ...
// and always do remember, in the end
for (int i = 0; i < 30; ++i)
    free(temp_struct[i]);
free(temp_struct);

Обратите внимание, что на самом деле это не массив структур, а скорее массив указателей на структуры - или даже массив массивов struct, если хотите. В последнем случае каждый вложенный массив будет иметь длину 1 (поскольку мы выделяем пространство только для одной структуры).

...