Ce face malloc
malloc (memory allocation) alocă size octeți pe heap și returnează un pointer la începutul blocului. Memoria rămâne alocată până când o eliberezi cu free, chiar și după ce funcția care a cerut-o s-a terminat.
Folosești memorie dinamică atunci când nu știi dimensiunea la compilare (de exemplu câte elemente citești) sau când datele trebuie să trăiască mai mult decât funcția curentă. Conținutul blocului nu este inițializat: conține valori la întâmplare până scrii în el. Dacă vrei zerouri, folosește calloc.
Forma recomandată este p = malloc(n * sizeof *p);: dimensiunea se calculează din tipul pointerului, deci rămâne corectă dacă schimbi tipul. În C nu ai nevoie de cast la rezultat. Verifică mereu dacă rezultatul este NULL.
Parametri
| Parametru | Descriere |
|---|---|
size |
Numărul de octeți ceruți (de tip size_t). Pentru n elemente: n * sizeof *p. |
Ce returnează
Un void * spre blocul alocat, aliniat pentru orice tip, sau NULL dacă memoria nu a putut fi alocată. Pentru size == 0 poate returna NULL sau un pointer unic, care tot trebuie eliberat cu free.
Exemple
Exemplul 1: Un tablou cu dimensiunea aflată la rulare
Numărul de note este citit de la intrare, apoi se alocă exact cât trebuie. La final memoria este eliberată.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n;
if (scanf("%zu", &n) != 1 || n == 0) return 0;
int *note = malloc(n * sizeof *note);
if (note == NULL) {
printf("Memorie insuficientă\n");
return 0;
}
int suma = 0;
for (size_t i = 0; i < n; i++) {
if (scanf("%d", ¬e[i]) != 1) note[i] = 0;
suma += note[i];
}
printf("%zu note, media %.2f\n", n, (double)suma / (double)n);
free(note);
return 0;
}
Ce scrie utilizatorul (intrare)
4
9 7 10 8
Rezultat
4 note, media 8.50
Exemplul 2: O structură care trăiește după funcție
Funcția creează un client pe heap și returnează pointerul. Cine îl primește trebuie să-l elibereze. Copierea numelui se face cu snprintf, care nu depășește tabloul.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char nume[40];
double sold;
} Client;
Client *client_nou(const char *nume, double sold) {
Client *c = malloc(sizeof *c);
if (c == NULL) return NULL;
snprintf(c->nume, sizeof c->nume, "%s", nume);
c->sold = sold;
return c;
}
int main(void) {
Client *c = client_nou("Ana Ionescu", 820.0);
if (c != NULL) {
printf("%s: %.2f lei\n", c->nume, c->sold);
free(c);
}
return 0;
}
Rezultat
Ana Ionescu: 820.00 lei
Exemplul 3: O copie a unui șir pe heap
Se alocă strlen + 1 octeți: unul în plus pentru '\0'. (C23 are deja funcția strdup care face asta.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *copiaza(const char *s) {
size_t lungime = strlen(s) + 1;
char *copie = malloc(lungime);
if (copie != NULL) memcpy(copie, s, lungime);
return copie;
}
int main(void) {
char *oras = copiaza("Timișoara");
if (oras == NULL) return 0;
printf("%s (%zu octeți alocați)\n", oras, strlen(oras) + 1);
free(oras);
return 0;
}
Rezultat
Timișoara (11 octeți alocați)
Greșeli frecvente
- Nu verifici rezultatul. Dacă
mallocreturneazăNULLși scrii în el, programul se oprește (sau mai rău). - Aloci
nocteți în loc denelemente:malloc(n)pentru un tablou deintdă un sfert din cât trebuie. Scriemalloc(n * sizeof *p). - Uiți locul pentru
'\0'când aloci un șir:malloc(strlen(s))e cu un octet prea puțin. - Uiți
free. Memoria rămâne ocupată până la terminarea programului (memory leak); într-un program care rulează mult timp, consumul crește continuu. - Citești memoria înainte să o inițializezi.
mallocnu pune zerouri; valorile sunt nedeterminate.
Comenzi înrudite
calloc: Alocă memorie pentru un tablou de count elemente a câte size octeți și pune zero în toți octeții.realloc: Schimbă dimensiunea unui bloc alocat dinamic, păstrând conținutul; poate muta blocul la altă adresă.free: Eliberează un bloc alocat cu malloc, calloc sau realloc, ca memoria să poată fi refolosită.void * (pointer generic): Un pointer care poate păstra adresa oricărui tip de date, dar care trebuie convertit la un tip concret înainte de folosire.sizeof: Operatorul care spune câți octeți ocupă un tip sau o variabilă; calculat de compilator, rezultatul are tipul size_t.strcpy, strncpy și strdup: Copiază un șir C într-un alt tablou (strcpy, strncpy) sau într-o zonă nouă alocată cu malloc (strdup).