Удаление динамически выделяемых элементов массива в C

#c #arrays #memory-management

#c #массивы #управление памятью

Вопрос:

Допустим, у меня есть массив структур, и я хочу удалить запись, которая имеет структуру с записью, соответствующей некоторым критериям.

Этот массив динамически выделяется с помощью malloc, я сохраняю количество элементов в отдельной переменной.

Как мне приступить к удалению записи?

Я думаю о

 for (i = pos; i < arr_len; i  ) {
  arr[i] = arr[i 1];
}
arr_len--;
  

Но это оставляет тот же объем памяти для массива, в то время как мне на самом деле нужно меньше и сирота (своего рода) последняя запись.

Является ли выполнение перераспределения в такой ситуации общепринятой практикой? Будет ли realloc выполнять memcpy в этом случае? (сокращение выделяемой памяти на один блок).

Ответ №1:

realloc все в порядке… но продолжайте читать 🙂

realloc не приведет к перемещению частей памяти; это может привести к перемещению всего блока. Поэтому вам необходимо скопировать данные перед изменением выделенного размера.

Для перемещения данных memmove (не memcpy ) является хорошим вариантом: это работает для областей памяти, которые принадлежат одному и тому же объекту. Однако обратите внимание на то, чтобы не выходить за пределы своего массива; как вы делаете в своем коде.

 for (i = pos; i < arr_len; i  ) {
  arr[i] = arr[i 1];
}
  

arr[i] = arr[i 1]; Попытается получить доступ к элементу, превышающему допустимый размер. Вам нужно

 for (i = pos   1; i < arr_len; i  ) {
  arr[i - 1] = arr[i];
}
  

При вызове возникают некоторые накладные расходы realloc . Если ваши структуры невелики и / или они живут недолго, рассмотрите возможность сохранения как количества элементов, так и количества выделенных элементов и перераспределения только для увеличения (когда (element_count 1) > (allocated_count) ).


Если структура большая, также рассмотрите другую структуру данных (возможно, связанный список).

Комментарии:

1. Спасибо за подсказку при доступе к последнему элементу. Я написал этот конкретный случай на бумаге, но все равно умудрился пропустить его, когда ненадолго забыл, что массивы индексируются с 0!

Ответ №2:

Вызов realloc для сокращения выделенной памяти не обязательно будет плохой идеей.

Однако вам, возможно, придется пересмотреть используемую структуру данных. Похоже, что связанный список значительно упростил бы управление памятью и значительно ускорил бы операцию удаления, поскольку для этого не требуется перенос элементов.

Ответ №3:

Здесь было бы уместно использовать realloc. Это не привело бы к выполнению memcpy — это необходимо только тогда, когда размер перераспределения больше и нет места для расширения.