Різниця між malloc і calloc?


779

Яка різниця між тим, що робити:

ptr = (char **) malloc (MAXELEMS * sizeof(char *));

або:

ptr = (char **) calloc (MAXELEMS, sizeof(char*));

Коли корисно використовувати calloc over malloc чи навпаки?



8
На C ви можете ptr = calloc(MAXELEMS, sizeof(*ptr));
сказати

7
Цікавий пост про різницю між calloc та malloc + memset vorpus.org/blog/why-does-calloc-exist
ddddavidee

2
@ddddavidee Я теж знайшов цей блог після того, як я був незадоволений такою кількістю відповідей в мережі. Натаніел Дж. Сміт заслуговує на 100+ балів для свого аналізу.
життєвий баланс

Відповіді:


849

calloc()дає вам нульовий ініціалізований буфер, при цьому malloc()залишає пам'ять неініціалізованою.

Для великих виділень більшість callocреалізацій під основними операційними системами отримуватимуть відомі нульові сторінки з ОС (наприклад, через POSIX mmap(MAP_ANONYMOUS)або Windows VirtualAlloc), тому не потрібно записувати їх у користувальницький простір. Ось як нормально mallocотримує і більше сторінок з ОС; callocпросто використовує гарантію ОС.

Це означає, що callocпам'ять все ще може бути "чистою" та ліниво виділеною, а копіювати при записі відображати на загальносистемну загальну фізичну сторінку нулів. (Припускаючи систему з віртуальною пам'яттю.)

Деякі компілятори навіть можуть оптимізувати malloc + memset (0) у calloc, але вам слід використовувати явно calloc, якщо ви хочете, щоб пам'ять читалася як 0.

Якщо ви не збираєтеся ніколи читати пам'ять перед її написанням, використовуйте mallocтак, що вона (потенційно) може дати вам брудну пам'ять із її внутрішнього безкоштовного списку замість отримання нових сторінок з ОС. (Або замість нулю блоку пам'яті у вільному списку для невеликого виділення).


Вбудовані реалізації програми callocможуть залишити її callocдо нульової пам'яті, якщо немає ОС, або це не фантазія багатокористувацької ОС, яка нульовує сторінки, щоб зупинити витік інформації між процесами.

У вбудованому Linux, malloc міг mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS), який увімкнено лише для деяких вбудованих ядер, оскільки це небезпечно для багатокористувацької системи.


224
Варіанти * аллоку досить мнемонічні - ясно-аллок, пам'ять-аллок, ре-аллок.
Каскабель

43
Використовуйте malloc (), якщо ви збираєтесь встановити все, що ви використовуєте, у виділеному просторі. Використовуйте calloc (), якщо ви збираєтесь залишити частини даних неініціалізованими - і було б корисно, щоб невідомі частини були нульовими.
Джонатан Леффлер

268
callocце не обов'язково дорожче, оскільки ОС може зробити деякі хитрощі, щоб пришвидшити його. Я знаю, що FreeBSD, коли отримує будь-який час простою процесора, використовує цей процес для запуску простого процесу, який просто обходить і зводить нанівець розміщені блоки пам'яті і маркує блоки таким чином, обробляючи прапор. Тож коли ви робите callocце, він спершу намагається знайти один із таких попередньо нульових блоків і просто надіслати його - і, швидше за все, він знайде його.
Павло Мінаєв

28
Я схильний вважати, що якщо ваш код стає "безпечнішим" у результаті виділення за нульовим призначенням за замовчуванням, то ваш код недостатньо безпечний, використовуєте ви malloc або calloc. Використання malloc - хороший показник того, що дані потребують ініціалізації - я використовую calloc лише у тих випадках, коли ці 0 байти мають значення. Також зауважте, що calloc не обов'язково робить те, що ви думаєте для нехарактерних типів. Ніхто більше не використовує уявлення про пастку або плаває не IEEE, але це не привід вважати, що ваш код справді портативний, коли його немає.
Стів Джессоп

18
@SteveJessop "Безпечніше" - не правильне слово. Я думаю, що "Детерміністичний" - кращий термін. Код, який є більш детермінованим, ніж тим, що має збої, які залежать від термінів і послідовностей даних, буде простіше виділити відмови. Calloc - це іноді простий спосіб отримати цей детермінізм проти явної ініціалізації.
dennis

362

Менш відома відмінність полягає в тому, що в операційних системах з оптимістичним розподілом пам’яті, як-от Linux, вказівник, який повертається, mallocне підтримується реальною пам'яттю, поки програма фактично не торкнеться цього.

callocдійсно торкається пам'яті (вона записує нулі на ній), і, таким чином, ви будете впевнені, що ОС підтримує розподіл фактичною оперативною пам’яттю (або свопом). Ось чому він повільніше, ніж malloc (він не тільки має нульовий рівень, ОС також повинен знайти відповідну область пам'яті, можливо замінивши інші процеси)

Дивіться, наприклад, це питання SO для подальшого обговорення поведінки malloc


49
callocне потрібно писати нулі. Якщо виділений блок складається здебільшого з нових нульових сторінок, наданих операційною системою, він може залишати ці недоторканими. Звичайно, це потрібно callocналаштовувати на операційну систему, а не на загальну функцію бібліотеки malloc. Або виконавець може змусити callocпорівнювати кожне слово проти нуля, перш ніж занулювати його. Це не заощадить жодного часу, але уникне забруднення нових сторінок.
R .. GitHub СТОП ДОПОМОГАЙТЕ

3
@R .. цікава примітка. Але на практиці чи існують такі реалізації в природі?
Ісак Саво

10
Усі dlmallocподібні реалізації пропускають, memsetякщо фрагмент був отриманий через mmapнові анонімні сторінки (або еквівалент). Зазвичай такий вид виділення використовується для більших часток, починаючи з 256k або близько того. Я не знаю жодної реалізації, яка проводить порівняння проти нуля, перш ніж записати нуль осторонь від мого власного.
R .. GitHub СТОП ДОПОМОГАЙТЕ

1
omallocтакож пропускає memset; callocне потрібно торкатися жодних сторінок, які вже не використовуються програмою (кеш сторінок). Хоча надзвичайно примітивні callocреалізації відрізняються.
mirabilos

10
calloc glibc перевіряє, чи отримує свіжу пам'ять з ОС. Якщо це так, він знає, що НЕ потрібно його писати, тому що mmap (..., MAP_ANONYMOUS) повертає вже нульову пам'ять.
Пітер Кордес

111

Однією з часто недооцінених переваг callocє те, що (відповідні реалізації) це допоможе захистити вас від цілих вразливих переповнень. Порівняйте:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

vs.

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

Перший може призвести до невеликого розподілу та подальшого переповнення буфера, якщо countвін перевищує SIZE_MAX/sizeof *bar. Остання автоматично вийде з ладу, оскільки великий об'єкт не може бути створений.

Звичайно, можливо, вам доведеться шукати невідповідні реалізації, які просто ігнорують можливість переповнення ... Якщо це турбує проблеми на платформах, на які ви орієнтуєтесь, вам доведеться все-таки зробити тест вручну на переповнення.


17
Мабуть, саме арифметичне переповнення стало причиною відкриття OpenSSH у 2002 році. Хороша стаття з OpenBSD про небезпеку цього з функціями, пов'язаними з пам’яттю: undeadly.org/cgi?action=article&sid=20060330071917
Philip P.

4
@KomradeP.: Цікаво. На жаль, стаття, яку ви пов’язали, має дезінформацію на початку. Приклад з charє НЕ переповнення , а скоріше визначається реалізацією перетворення при призначенні результат назад у вигляді charоб'єкта.
R .. GitHub СТОП ДОПОМОГАТИ ДВІ

Це, мабуть, лише для ілюстрації. Тому що компілятор, швидше за все, оптимізує це. Шахта збирається в цей асм: push 1.
Філіп П.

1
@tristopia: Справа не в тому, що код можна використовувати у всіх реалізаціях, а в тому, що він невірний без додаткових припущень і, таким чином, не правильного / портативного використання.
R .. GitHub СТОП ДОПОМОГА ВІД

3
@tristopia: Якщо ваш режим мислення " size_t64-бітний, тому це не проблема", це хибний спосіб мислення, який призведе до помилок у безпеці. size_tце абстрактний тип , який представляє розміри, і немає ніяких підстав вважати , довільне твір 32-бітного числа і size_t(примітка: sizeof *barв принципі може бути більше , ніж 2 ^ 32 на реалізацію в 64-бітному C!) уміщається в size_t.
R .. GitHub СТОП ДОПОМОГА ВІД

37

Документація робить calloc схожим на malloc, який просто робить ініціалізацію пам'яті; це не первинна різниця! Ідея calloc полягає у відміні семантики копіювання на запис для розподілу пам'яті. Якщо ви виділяєте пам'ять з calloc, все це відображається на ту саму фізичну сторінку, яка ініціалізується до нуля. Коли будь-яка зі сторінок виділеної пам'яті записується у фізичну сторінку, виділяється. Це часто використовується для створення ВЕЛИЧЕЗНИХ хеш-таблиць, наприклад, оскільки порожні частини хеша не підтримуються додатковою пам'яттю (сторінки); вони із задоволенням вказують на єдину нульову ініціалізовану сторінку, яку можна розділити навіть між процесами.

Будь-яке записування на віртуальну адресу відображається на сторінку, якщо ця сторінка - нульова сторінка, виділяється інша фізична сторінка, нульова сторінка копіюється туди, а потік управління повертається до клієнтського процесу. Це працює так само, як працюють файли, відображені в пам'яті, віртуальна пам'ять тощо. Він використовує підкачку.

Ось одна історія оптимізації цієї теми: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/


26

Немає різниці у розмірі виділеного блоку пам'яті. callocпросто заповнює блок пам’яті фізичним малюнком з усіх нульових біт. На практиці часто передбачається, що об'єкти, розташовані в виділеному з блоку пам'яті, callocмають ініціальне значення так, ніби вони були ініціалізовані буквально 0, тобто цілі числа повинні мати значення 0змінних з плаваючою комою - значення 0.0, вказівники - відповідного значення нульового вказівника , і так далі.

З педантичної точки зору, хоча calloc(як і memset(..., 0, ...)) гарантується лише належна ініціалізація (з нулями) об'єктів типу unsigned char. Все інше не гарантується належним чином ініціалізувати і може містити так зване уявлення про пастку , що спричиняє не визначену поведінку. Іншими словами, для будь-якого типу, окрім unsigned charвищезгаданого patterm all-zero-bits, може бути неправомірне значення, подання в пастку.

Пізніше в одному зі стандартів Технічної корекції до С99 поведінка була визначена для всіх цілих типів (що має сенс). Тобто формально, в поточній мові C ви можете ініціалізувати лише цілі типи з callocmemset(..., 0, ...)). Використання його для ініціалізації будь-чого іншого в загальному випадку призводить до невизначеної поведінки, з точки зору мови С.

На практиці це callocпрацює, як ми всі знаємо :), але чи бажаєте ви ним користуватися (з огляду на вищесказане). Я особисто вважаю за краще уникати цього, використовувати mallocзамість цього і виконувати власну ініціалізацію.

Нарешті, ще одна важлива деталь є те , що callocпотрібно , щоб обчислити остаточний розмір блоку всередині , шляхом множення розміру елемента за кількістю елементів. Роблячи це, callocнеобхідно стежити за можливим арифметичним переповненням. Це призведе до невдалого розподілу (нульовий покажчик), якщо запитуваний розмір блоку неможливо правильно розрахувати. Тим часом ваша mallocверсія не намагається стежити за переповненням. Він виділить деякий "непередбачуваний" об'єм пам'яті у випадку, якщо відбудеться переповнення.


Згідно з пунктом "ще одна важлива деталь": це, здається, створює memset(p, v, n * sizeof type);проблему, оскільки n * sizeof typeможе переповнитися. Гадаю, мені знадобиться використовувати for(i=0;i<n;i++) p[i]=v;цикл для надійного коду.
chux

Було б корисно, якби існували стандартні засоби, за допомогою яких код міг би стверджувати, що імплементація повинна використовувати all-bits-zero як нульовий покажчик (відмовляючись від компіляції в іншому випадку), оскільки існують реалізації, які використовують інші представлення null-pointer, але вони є порівняно рідкісні; код, який не повинен запускатися на таких реалізаціях, може бути швидшим, якщо він може використовувати calloc () або memset для ініціалізації масивів покажчиків.
supercat

@chux Ні, якщо масив з nелементами існує там, де елемент має розмір sizeof type, він n*sizeof typeне може переповнюватись, оскільки максимальний розмір будь-якого об'єкта повинен бути меншим за SIZE_MAX.
12431234123412341234123

@ 12431234123412341234123 Правда, розмір масиву <= SIZE_MAX, але масивів тут немає . Вказівник, повернутий з, calloc()може вказувати на виділену пам'ять, ніж перевищує SIZE_MAX. Багато реалізацій обмежують добуток двох аргументів calloc()до SIZE_MAX, але специфіка C не встановлює цього обмеження.
chux

21

зі статті Бенчмаркінг забави з calloc () і нульових сторінок на блозі Georg Hager в

При розподілі пам’яті за допомогою calloc () запитуваний обсяг пам’яті не виділяється відразу. Натомість всі сторінки, що належать до блоку пам'яті, з'єднуються в одну сторінку, що містить усі нулі деякою магією MMU (посилання нижче). Якщо такі сторінки читаються лише (що було справедливо для масивів b, c і d в оригінальній версії еталону), дані надаються з єдиної нульової сторінки, що, звичайно, вписується в кеш. Стільки для ядер циклу, пов'язаного з пам'яттю. Якщо сторінка записується на (незалежно від того, як), відбувається помилка, відображається "реальна" сторінка, а нульова сторінка копіюється в пам'ять. Це називається відомим підходом до оптимізації (що я навіть кілька разів викладав на своїх C ++ лекціях). Після того,


де посилання?
Рупеш Ядав.

2
перший рядок відповіді містить посилання на щоденник Георга Хагера.
Ашіш Чаван

11

callocзазвичай malloc+memsetдо 0

Зазвичай трохи краще використовувати malloc+memsetявно, особливо коли ви робите щось на кшталт:

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

Це краще, тому що sizeof(Item)це відомо компілятору під час компіляції, і компілятор у більшості випадків замінить його найкращими можливими інструкціями щодо нульової пам'яті. З іншого боку, якщо memsetвідбувається в calloc, розмір параметра розподілу не компілюється в callocкоді і memsetчасто називається реальним , який, як правило, містить код для заповнення байта за байтом до довгої межі, ніж цикл для заповнення збільшити об'єм пам'яті sizeof(long)і, нарешті, байт-байт заповнити залишок місця. Навіть якщо розподільник досить розумний, щоб викликати деякі, aligned_memsetвін все одно буде загальним циклом.

Одним з помітних винятків буде те, коли ви робите malloc / calloc дуже великого фрагмента пам'яті (деякий power_of_two кілобайт), у цьому випадку виділення може здійснюватися безпосередньо з ядра. Оскільки ядра ОС зазвичай нулюють всю пам'ять, яку вони віддають з міркувань безпеки, досить розумний calloc може просто повернути її без додаткових нулювань. Знову ж таки - якщо ви просто виділяєте те, що ви знаєте, мало, вам може бути краще з функцією malloc + memset.


+1 для нагадування, що загальна реалізація функціоналу в системній бібліотеці не обов'язково швидша, ніж та сама операція в коді користувача.
Патрік Шлютер

1
Існує також другий момент, який робить calloc()повільніше, ніж malloc(): множення на розмір. calloc()потрібно використовувати загальне множення (якщо size_tце 64 біт, навіть дуже затратні 64 біти * 64 біти = 64 біти), тоді як у malloc () часто буде константа часу компіляції.
Патрік Шлютер

4
glibc calloc має деякі розумні можливості вирішити, як найефективніше очистити повернутий фрагмент, наприклад, іноді потрібна очистка лише його частини, а також нерозгорнута очистка розміром до 9 * (size_t). Пам'ять - це пам'ять, очищення її за 3 байти одночасно не буде швидше тільки тому, що ви потім будете використовувати її для утримання struct foo { char a,b,c; };. callocзавжди краще, ніж malloc+ memset, якщо ви завжди збираєтесь очистити всю mallocобласть редагування. callocтакож ретельно, але ефективно перевіряє наявність int overflow у розмірах * елементів.
Пітер Кордес

8

Різниця 1:

malloc() зазвичай виділяє блок пам'яті і це ініціалізований сегмент пам'яті.

calloc() виділяє блок пам'яті та ініціалізує весь блок пам'яті до 0.

Різниця 2:

Якщо врахувати malloc()синтаксис, знадобиться лише 1 аргумент. Розглянемо наступний приклад нижче:

data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );

Наприклад: Якщо ви хочете виділити 10 блоків пам'яті для типу int,

int *ptr = (int *) malloc(sizeof(int) * 10 );

Якщо ви розглядаєте calloc()синтаксис, знадобиться 2 аргументи. Розглянемо наступний приклад нижче:

data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

Наприклад: якщо ви хочете виділити 10 блоків пам'яті для типу int та ініціалізувати все це на ZERO,

int *ptr = (int *) calloc(10, (sizeof(int)));

Схожість:

Обидва malloc()і calloc()повернуть недійсним * за замовчуванням, якщо вони не будуть типовими.


І чому ви зберігаєте data_type та cast_type різними?
Продається

7

Є дві відмінності.
По-перше, в кількості аргументів. malloc()бере один аргумент (потрібна пам'ять у байтах), тоді як calloc()потрібні два аргументи.
По-друге, malloc()не ініціалізує виділену пам'ять, в той час як calloc()ініціалізує виділену пам'ять на ZERO.

  • calloc()виділяє область пам'яті, довжина буде добуток її параметрів. callocзаповнює пам'ять ZERO і повертає вказівник на перший байт. Якщо він не знайде достатньо місця, він повертає NULLвказівник.

Синтаксис: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); тобтоptr_var=(type *)calloc(n,s);

  • malloc()виділяє єдиний блок пам'яті REQUSTED SIZE і повертає вказівник на перший байт. Якщо не вдасться знайти відновлений об'єм пам'яті, він повертає нульовий покажчик.

Синтаксис: функція приймати один аргумент, який є кількістю байт для розподілу, в той час як функція приймає два аргументи, один з яких числа елементів, а інша кількість байт для розподілу для кожного з цих елементів. Крім того, ініціалізує виділений простір до нулів, а не робить.ptr_var=(cast_type *)malloc(Size_in_bytes);malloc()calloc()calloc()malloc()


6

calloc()Функція , яка оголошена в <stdlib.h>заголовку пропонує кілька переваг по порівнянні з malloc()функцією.

  1. Він виділяє пам'ять як ряд елементів заданого розміру, і
  2. Він ініціалізує пам'ять, яка виділяється так, що всі біти дорівнюють нулю.

6

malloc()і calloc()це функції зі стандартної бібліотеки С, які дозволяють динамічно розподіляти пам'ять, тобто вони обидва дозволяють розподілити пам'ять під час виконання.

Їх прототипи такі:

void *malloc( size_t n);
void *calloc( size_t n, size_t t)

В основному існують дві різниці між ними:

  • Поведінка: malloc()виділяє блок пам'яті, не ініціалізуючи його, і зчитування вмісту з цього блоку призведе до значень сміття. calloc()з іншого боку, виділяє блок пам'яті та ініціалізує його на нулі, і очевидно, що читання вмісту цього блоку призведе до нулів.

  • Синтаксис: malloc()приймає 1 аргумент (розмір, який повинен бути призначений), і calloc()бере два аргументи (кількість блоків, які потрібно виділити, і розмір кожного блоку).

Повернене значення з обох є вказівником на виділений блок пам'яті, якщо це вдало. В іншому випадку повернеться NULL , що вказує на збій розподілу пам'яті.

Приклад:

int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));

Ж функціональні можливості, як calloc()можна досягти з допомогою malloc()і memset():

// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 

Зверніть увагу, що malloc()його переважно використовувати над calloc()тим, що це швидше. Якщо потрібна нульова ініціалізація значень, використовуйте calloc()замість цього.


5

Ще не вказана різниця: обмеження розміру

void *malloc(size_t size)може виділити лише до SIZE_MAX.

void *calloc(size_t nmemb, size_t size);може виділити близько SIZE_MAX*SIZE_MAX.

Ця здатність не часто використовується на багатьох платформах з лінійною адресацією. Такі системи обмежують calloc()з nmemb * size <= SIZE_MAX.

Розглянемо тип 512 байт, який називається, disk_sectorі код хоче використовувати безліч секторів. Тут код може використовуватись лише до SIZE_MAX/sizeof disk_sectorсекторів.

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

Розглянемо наступне, що дозволяє ще більше розподілити.

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

Тепер, якщо така система може забезпечити такий великий розподіл - інша справа. Більшість сьогодні цього не зробить. Тим не менш, це відбувалося протягом багатьох років, коли SIZE_MAXбуло 65535. Зважаючи на закон Мура , підозрюйте, що це відбудеться приблизно в 2030 році з певними моделями SIZE_MAX == 4294967295пам'яті і пулами пам'яті в 100 Гбіт.


2
Як правило, size_t зможе вмістити розмір найбільшого виду об’єктів, з яким може оброблятися програма. Система, де size_t становить 32 біти, навряд чи зможе обробити розподіл, більший за 4294967295 байт, а система, яка змогла б обробляти виділення такого розміру, майже напевно зробила б size_tбільше 32 біт. Питання лише в тому, чи можна використовувати callocзначення зі значеннями, продукт яких перевищує, SIZE_MAXщоб отримати нуль, а не повернути вказівник на менший розмір.
supercat

Погодьтеся щодо вашого узагальнення , але специфікація C дозволяє calloc()виділяти більше, ніж SIZE_MAX. Це відбувалося в минулому з 16-бітною size_tверсією, і оскільки пам'ять продовжує здешевлюватися, я не бачу причин, що це не може відбутися вперед навіть у тому випадку, якщо це не є загальним явищем .
chux

1
Стандарт C дає можливість коду вимагати виділення, розмір якого перевищує SIZE_MAX. Це, звичайно, не вимагає наявності обставин, за яких таке розподіл може бути успішним; Я не впевнений, що якась особлива користь від мандатів на те, що реалізації, які не можуть обробляти такі розподіли, повинні повертатися NULL(особливо якщо врахувати, що для деяких реалізацій є загальні mallocпокажчики повернення до місця, яке ще не здійснено і може бути недоступним, коли код насправді намагається використовувати це).
supercat

Крім того, там, де раніше існували системи, доступний діапазон адрес яких перевищував найбільше представлене ціле число, я не бачу реальної можливості, щоб це знову виникало, оскільки для цього потрібна була б ємність в мільярди гігабайт. Навіть якби закон Мура продовжував дотримуватися, перехід від точки, коли 32 біта перестає бути достатньою до тієї точки, коли 64 біт перестає бути достатньою, знадобиться вдвічі більше, ніж дістатися з точки, де 16 біт було достатньо, до точки, де 32 не було 'т.
supercat

1
Чому реалізація яких може вмістити один виділення в надлишку 4G не визначають size_tв uint64_t?
supercat

2

Кількість блоків:
malloc () призначає один блок запитуваної пам'яті,
calloc () призначає кілька блоків запитуваної пам'яті

Ініціалізація:
malloc () - не очищає та ініціалізує виділену пам'ять.
calloc () - ініціалізує виділену пам'ять на нуль.

Швидкість:
malloc () - швидкий.
calloc () повільніше, ніж malloc ().

Аргументи та синтаксис:
malloc () бере 1 аргумент:

  1. байт

    • Кількість байтів, які потрібно виділити

calloc () бере 2 аргументи:

  1. довжина

    • кількість блоків пам'яті, які потрібно виділити
  2. байт
    • кількість байтів, які потрібно виділити кожному блоку пам'яті
void *malloc(size_t bytes);         
void *calloc(size_t length, size_t bytes);      

Спосіб розподілу пам'яті:
Функція malloc призначає пам'ять потрібного "розміру" з доступної купи.
Функція calloc призначає пам'ять, розмір якої дорівнює "num * size".

Значення імені:
ім'я malloc означає "розподіл пам'яті".
Назва calloc означає "безперервне виділення".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.