#c #arrays #struct #realloc
#c #массивы #структура #перераспределить
Вопрос:
Я пытаюсь динамически перераспределить память для массива структур (на самом деле это массив, каждый из 2 структур, но 1 включен здесь для простоты), который считывается из / в файл или вводится пользователем.
typedef Struct
{
char surname[21];
char firstname[21];
char username[21];
...
} User;
…в main():
int size = 0; /* stores no. of structs */
User* user_array = (User *) calloc(1, sizeof(User));
if(user_array == NULL)
{
printf("Cannot allocate initial memory for datan");
exit(1);
}
else
size ;
Затем я пытаюсь использовать вызов функции для увеличения массива, когда это необходимо:
int growArray(User user_array*, int size)
{
User *temp;
size ;
temp = (User *) realloc(user_array, (size * sizeof(User));
if(temp == NULL)
{
printf("Cannot allocate more memory.n");
exit(1);
}
else
user_array = temp;
return size;
}
К сожалению, перераспределение никогда не работает. Размер обеих структур составляет всего около 200 байт на экземпляр, и установка начального размера, скажем, 10, будет работать нормально, поэтому, должно быть, что-то не так с тем, как я пытаюсь использовать realloc.
Система — Win 7 64, на Core i5 с 4 ГБ, работает под управлением Quincy (графический интерфейс MinGW).
Комментарии:
1.
int growArray(User user_array, int size)
? Вам не хватает*
?2. опубликуйте реальный код — он не будет компилироваться
3. @KennyTM Я думаю, что ему не хватает двух из них.
4. Если вы заставите это работать, вы можете упростить код, также выполнив первоначальное выделение с помощью growArray. Также имейте в виду, что ваш первоначальный calloc() инициализирует первую запись, в то время как последующий realloc () оставит расширенную область неинициализированной. Как отмечает cnicutar, «размер » не будет виден вызывающей стороне.
5. дантье — на данный момент я использую size для возвращаемого значения — извините, что не учитываю это
Ответ №1:
realloc
изменяет размер памяти, на которую указывает user_array
, на указанный размер, это не увеличивает его на размер. Видя, как вызывается ваша функция growArray
, я бы предположил, что вы хотите, чтобы она увеличила размер массива на size
, и в этом случае вам нужно:
int growArray(User **user_array, int currentSize, int numNewElems)
{
const int totalSize = currentSize numNewElems;
User *temp = (User*)realloc(*user_array, (totalSize * sizeof(User)));
if (temp == NULL)
{
printf("Cannot allocate more memory.n");
return 0;
}
else
{
*user_array = temp;
}
return totalSize;
}
Обратите внимание, что это growArray
принимает адрес user_array
, причина этого в том, что realloc
это может привести к перемещению памяти, если не удастся расширить существующий блок до требуемого размера.
Чтобы использовать его:
int size = 0;
User* user_array = (User *) calloc(1, sizeof(User));
if(user_array == NULL)
{
printf("Cannot allocate initial memory for datan");
exit(1);
}
/* add 10 new elements to the array */
size = growArray(amp;user_array, size, 10);
Комментарии:
1. Размер равен количеству структур в массиве (до его увеличения), когда он передается в growArray. Размер в growArray увеличит это значение до нового числа (предполагается, что оно будет увеличиваться на 1 за раз — из-за неизвестного количества записей в файле или путем добавления пользователем), поэтому я считаю, что размер * sizeof (User) является правильным для этого подхода. Я заметил, что вы использовали оператор двойного косвенного обращения, как это сделал @cnicutar, я все еще пытаюсь разобраться в том, что там происходит. Должно быть, в этом я ошибаюсь… если я не сделаю это таким образом, я все равно буду использовать старый начальный адрес user_array?
2. Да, это может быть вашей проблемой.
realloc
возможно, не удастся расширить существующийuser_array
блок памяти указателей, чтобы он был достаточно большим для нового размера. Если это происходит, он выделяет новый блок памяти где-то в другом месте и копирует все сuser_array
начала. Возвращаемое значение — это новая ячейка памяти. Использование указателя на указатель позволяетgrowArray
обновить значениеuser_array
вызывающего объекта, поскольку его предыдущее значение теперь недействительно.
Ответ №2:
Вы меняете значение user_array локально. Значение теряется при возврате функции. Вместо этого передайте указатель на указатель user_array.
Комментарии:
1. Извините, я забыл добавить * в свой приведенный выше код … теперь это исправлено.
2. Спасибо — это была проблема. Я не понимал, пока другие постеры не были более конкретными о том, как это сделать.