В чем разница между malloc() и calloc() а также free() и dellete()?

Допустим мы выделаем память
int *x = (int*) malloc(10);
int *y = (int*) calloc(10, sizeof(int));

У них есть 2 разницы
calloc выделяет память под массив данных, предварительно инициализируя её нулями. принимает 2 аргумента.
malloc выделяет память без инициализации. принимает один аргумент.

Но в принципе оба эти функций делают одно и тоже, в чем их разница ?
Где то читал что calloc создает ячейки определенного типа и обединяет их, к примеру int может быть 4 байта, и если мы напишем
int *y = (int*) calloc(3, sizeof(int));
То он создаст 12 ячеек, 4 4 4 и в каждом из 4 байтов будет храниться цифра 0.

int *x = (int*) malloc(12);
Тоже создаст 12 ячеек но если к примеру, в него добавим первый 4 байт цифру 9, в другой байт "string", а в другой вообще bool, как он определит что в нем находиться ?

Если в случае с calloc он знает что через каждые 4 байта у него есть цифра, то как в malloc он определит, что через каждые разные количество байтов у него разные количество элементов, Или он определяет свои элементы совсем по другому, в этапе компиляций и т.д.?
  • Вопрос задан
  • 29847 просмотров
Решения вопроса 1
@res2001
Developer, ex-admin
Разница только в том, что calloc обнуляет выделенную память перед тем, как возвратить указатель, а malloc этого не делает. Внутри calloc, наверняка вызывает malloc для выделения памяти, а потом memset для обнуления. Так что calloc это просто надстройка над malloc для удобства. Вот схематично реализация calloc:
void * calloc (size_t num, size_t size)
{
   void * mem = malloc(num * size);
  memset(mem, 0, num * size);
  return mem;
}

Сами эти функции оперируют исключительно размером выделяемой области в байтах, им все равно что вы в дальнейшем будете делать с выделенной памятью - инты туда писать или "стринги".
Ну и как бы никто не мешает вам одну и ту же область памяти сначала использовать как массив интов, а потом как массив байт. Или так например:
int a = 0x33323130;
char * c = (char*)&a;
printf("%c %c %c %c\n", c[0], c[1], c[2], c[3]);

Пример не использует malloc/calloc для выделения памяти, память выделяется в стеке просто объявлением int a. Тут я попытался показать, что содержимое памяти можно интерпретировать как угодно, главное находится в границах выделенного диапазона.
Причем языки С/С++/asm это позволяют делать, а другие - нет.
Пример предполагает, что int имеет размер 32 бита, не для всех платформ это так, но в основном - именно так.
Кстати этот пример можно использовать для определения порядка байтов платформы: если выведется "1 2 3 4" значит у вас LITTLE ENDIAN, а если "2 1 4 3" - BIG ENDIAN.

PS: free() - это Си, а delete - C++
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
zagayevskiy
@zagayevskiy
Android developer at Yandex
Разница именно в заполнении нулями (инициализации). Про определение что где находится я не понял. Си вообще никак это не отслеживает. Обе функции отдают вам абсолютно идентичные указатели, что с ними делать - ваша забота.
Про разные сигнатуры - говорят, что calloc при умножении аргументов следит за целочисленным переполнением и возвращает NULL в случае, когда оно произошло. С malloc нужно делать это самому.
Ответ написан
Комментировать
solotony
@solotony
покоряю пик Балмера
если вы программируете на с++ то лучше не выделять память при помощи malloc/calloc а создавать массивы объектов или базовых типов через new. а для прямой работы с памятью надо иметь очень весомое обоснование.

нет такого dellete()

есть оператор delete который освобождает то что выделено new
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы