In C, malloc e free permettono di gestire la memoria nell'heap a runtime. malloc alloca un blocco di byte, restituendo un puntatore void*; free rilascia il blocco. Ogni malloc deve avere il suo free per evitare memory leak.
Per creare una stringa modificabile a runtime, allochiamo spazio con malloc per lunghezza + 1 (terminatore '\0').
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// 1. Allochiamo spazio per 30 caratteri (29 + terminatore)
char *nome = (char*)malloc(30 * sizeof(char));
// 2. Controllo di errore fondamentale!
if (nome == NULL) {
printf("Errore allocazione memoria\n");
return 1;
}
// 3. Copia della stringa
strcpy(nome, "Alice");
printf("Nome: %s\n", nome);
// 4. Per estendere la stringa:
// Allochiamo NUOVA area più grande, copiamo e liberiamo la vecchia.
char *nuovo_nome = (char*)malloc(60 * sizeof(char));
if (nuovo_nome != NULL) {
strcpy(nuovo_nome, nome);
strcat(nuovo_nome, " - studentessa dinamica");
free(nome); // libero il vecchio blocco
nome = nuovo_nome; // aggiorno il puntatore
printf("Nome esteso: %s\n", nome);
} else {
printf("Estensione fallita, manteniamo il nome originale.\n");
}
// 5. Liberazione finale
free(nome);
nome = NULL;
return 0;
}
30 * sizeof(char) = 30 byte.Array di int con dimensione scelta a runtime. Usiamo malloc e per estendere la capacità: nuovo array più grande, copia manuale e infine free.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("Quanti elementi vuoi inserire? ");
scanf("%d", &n);
// Allocazione vettore di n interi
int *vett = (int*)malloc(n * sizeof(int));
if (vett == NULL) {
printf("Allocazione fallita\n");
return 1;
}
// Riempimento
for (int i = 0; i < n; i++) {
vett[i] = (i + 1) * 10;
}
printf("Vettore iniziale: ");
for (int i = 0; i < n; i++) {
printf("%d ", vett[i]);
}
printf("\n");
// --- Espansione del vettore: nuova capacità (n*2) ---
int nuova_capacita = n * 2;
int *nuovo_vett = (int*)malloc(nuova_capacita * sizeof(int));
if (nuovo_vett != NULL) {
// Copia elementi vecchi
for (int i = 0; i < n; i++) {
nuovo_vett[i] = vett[i];
}
// Riempiamo i nuovi elementi
for (int i = n; i < nuova_capacita; i++) {
nuovo_vett[i] = 100 + i;
}
free(vett); // rilascio vecchio array
vett = nuovo_vett; // riaggancio al nuovo blocco
printf("Vettore espanso (dimensione %d): ", nuova_capacita);
for (int i = 0; i < nuova_capacita; i++) {
printf("%d ", vett[i]);
}
printf("\n");
} else {
printf("Espansione fallita, mantengo vettore originale.\n");
}
// Liberazione finale
free(vett);
vett = NULL;
return 0;
}
n * sizeof(int) byte.int *data = (int*)malloc(100 * sizeof(int));
// ... operazioni ...
free(data);
data = NULL; // Evita dangling pointer
free non modifica il puntatore, ma rende la memoria nuovamente disponibile. Accedere dopo free è undefined behavior.
free(ptr); free(ptr); → corruzione heap. Imposta sempre ptr = NULL dopo free.
| Caratteristica | Stringa dinamica (char*) | Vettore dinamico (int*) |
|---|---|---|
| Allocazione tipica | malloc((len + 1) * sizeof(char)) |
malloc(n * sizeof(int)) |
| Terminatore obbligatorio | Sì, '\0' per le funzioni stringa | No, si conosce la dimensione separatamente |
| Espansione | malloc nuova area → strcpy → free vecchia | malloc nuova area → ciclo copia → free vecchia |
| Liberazione | free(ptr); ptr = NULL; |
|