2012-08-29 2 views
8

Только начал изучать C и наткнулся на следующий вопрос:Shrink целочисленный массив C

мне нужно сжать целочисленный массив в C, удаление в конце элементов. Устраняя, я имею в виду освобождение. Общий ответ - выделить новую память для меньшего массива, после чего скопировать все элементы (-элементы для удаления) исходного массива в недавно выделенную память, а затем освободить() исходный массив.

Поскольку я должен иметь дело с очень больших массивов, я бы скорее пропустил часть копирования.

Возможно ли создать указательную переменную, которая указывает на «ближе к концу исходного массива» размера «конец массива - ближе к концу», а затем освободить этот указатель?

Заранее спасибо

+1

Вы можете сжимать, используя 'realloc'. Это не гарантируется, но некоторые реализации фактически вернут вам исходный указатель, который вы передали, без копирования чего-либо. – cnicutar

+0

Считаете ли вы использование 'realloc'? –

+0

Будет ли realloc также освобождать все элементы в конце? Я бы не знал, как проверить это ... спасибо за быстрый ответ! –

ответ

4

realloc функции из стандартной библиотеки C может быть то, что вы хотите.

В вашем случае, скорее всего, НЕ выполнить операцию копирования, так как диспетчер памяти не имеет причин выделять новую зону памяти. Только разница между старым и новым размером может быть освобождена системой как доступная память.

Копирование произойдет в том случае, если вы сделаете свой массив больше, потому что malloc и друзья не гарантируют, что память после «текущей» зоны фактически бесплатна. Если это так, тогда все в порядке, текущее распределение памяти будет расширено. Если нет, необходимо найти большую доступную зону памяти, и ее можно распределить практически в любом месте в памяти.

+0

Это также, вероятно, фактически не освобождает память для повторного использования. – ddyer

+0

@ddyer Это просто не так ... сжатие буфера через realloc делает освобожденную память доступной для malloc (если она не меньше размера блока malloc). Он не может вернуть память в ОС, но также не будет malloc/copy/free. –

+0

Спасибо за четкий ответ. Но то, что сказал ddyer, действительно беспокоит меня. –

0

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

0

Я бы использовал realloc. Realloc может скопировать память, но это все равно может быть более эффективным, чем использование собственного управления памятью для борьбы с проблемой копирования.

Некоторые скажут вам, что некорректная библиотека C будет копировать, когда результирующий размер меньше. Вероятно, они правы. Тем не менее, я не использую или не пишу коммерческие библиотеки C, поэтому, насколько мне известно, требование необоснованно.

+0

За исключением специального случая отладки опций, которые предотвращают освобождение памяти, все коммерческие библиотеки переадресовывают, избегая копирования, если размер сжимается (или остается неизменным) ... почему бы и нет? –

+0

Согласен; хотя, насколько мне известно, это не гарантируется/в спецификации. – Tom

+0

Люди продолжают говорить о гарантиях из спецификации в ответ на мои комментарии, которые ничего не говорят об этом. Спецификация не гарантирует, что malloc когда-либо вернет ничего, кроме NULL. Важное значение имеет понимание технических характеристик, но если это все понятно, это педантизм, а не инженерное дело. –

1

Вы подумали об использовании realloc?

int main(void) 
{ 
    int *array = NULL, *tmp; 

    if(!(array = malloc(5 * sizeof(int)))) return 1; 
    if(!(tmp = realloc(array, 2*sizeof(int)))) 
    { 
     free(array); 
     return 1; 
    } 
    array = tmp; 
} 

Вы можете сделать это без tmp указателя и просто array = realloc(array, 2*sizeof(int)))), но это может привести к проблемам в дальнейшем вниз по дороге.