Dynamische Speicherallokation in C: malloc, calloc, realloc und free meistern
Bevor wir in die dynamische Speicherallokation in C eintauchen, ist es essenziell zu verstehen, wie Speicherverwaltung in der Sprache funktioniert.
Wie Speicherverwaltung in C funktioniert
Wenn Sie eine Variable mit einem primitiven Typ deklarieren, allokiert der Compiler automatisch Speicherplatz dafür auf dem Stack. Zum Beispiel belegt ein float typischerweise 4 Bytes (plattformabhängig). Dies können Sie mit dem sizeof-Operator bestätigen:
#include <stdio.h>
int main() {
float x;
printf("The size of float is %d bytes", sizeof(x));
return 0;
}
Ausgabe:
The size of float is 4 bytes
Ein Array fester Größe wird ebenfalls kontiguierlich auf dem Stack allokiert, wobei jedes Element die Größe seines Typs einnimmt:
#include <stdio.h>
int main() {
float arr[10];
printf("The size of the float array with 10 elements is %d", sizeof(arr));
return 0;
}
Ergebnis:
The size of the float array with 10 elements is 40
Während Stack-Allokation automatisch ist, benötigen viele Programme Speicher, dessen Größe erst zur Laufzeit bekannt ist. Dieser Bedarf wird durch dynamische Speicherallokation gedeckt, die den Heap statt des Stacks nutzt.
Dynamische Speicherallokation in C
Dynamische Allokation beinhaltet manuelles Anfordern und Freigeben von Speicher nach Bedarf, wobei Zeiger die allokierten Blöcke auf dem Heap verfolgen. Die C-Standardbibliothek stellt mehrere Funktionen dafür bereit:
- malloc() – Allokiert einen zusammenhängenden Block von Bytes und gibt einen Zeiger auf dessen erstes Byte zurück.
- calloc() – Allokiert ein Array von Elementen, initialisiert alle Bytes auf Null und gibt Zeiger auf erstes Element zurück.
- realloc() – Ändert die Größe eines zuvor allokierten Blocks, wobei Inhalt erhalten bleibt.
- free() – Gibt einen zuvor allokierten Block an den Heap zurück.
Lassen Sie uns jede Funktion im Detail betrachten.
malloc() Funktion
Die malloc()-Funktion steht für „memory allocation“. Sie reserviert einen Speicherblock der angegebenen Größe und gibt einen Zeiger darauf zurück. Der Zeiger wird typischerweise in den gewünschten Typ gecastet:
ptr = (cast_type *) malloc(byte_size);
Beispiel:
#include <stdlib.h>
int main() {
int *ptr;
ptr = malloc(15 * sizeof(*ptr)); /* 15 Integers */
if (ptr != NULL) {
*(ptr + 5) = 480; /* sechstes Element */
printf("Value of the 6th integer is %d", *(ptr + 5));
}
}
Ausgabe:
Value of the 6th integer is 480
Wichtige Punkte:
- Nutzen Sie
sizeof(*ptr), um Code robust gegen Typänderungen zu machen. - Prüfen Sie auf
NULL-Rückgabe, um Allokationsfehler zu erkennen. - Allokierter Speicher ist kontiguierlich; behandeln Sie ihn wie ein Array und nutzen Sie Zeigerarithmetik.
Dynamische Allokation ist nicht auf primitive Typen beschränkt; sie funktioniert mit Strukturen, Zeichen-Arrays und mehr.
free() Funktion
Mit malloc(), calloc() oder realloc() allokierter Speicher muss explizit freigegeben werden, um Leaks zu vermeiden. free() erledigt dies:
#include <stdio.h>
int main() {
int* ptr = malloc(10 * sizeof(*ptr));
if (ptr != NULL) {
*(ptr + 2) = 50;
printf("Value of the 2nd integer is %d", *(ptr + 2));
}
free(ptr);
}
Ausgabe:
Value of the 2nd integer is 50
calloc() Funktion
calloc() allokiert mehrere Blöcke gleicher Größe und initialisiert jedes Byte auf Null, ideal für Arrays und Strukturen, die nullten Speicher benötigen:
ptr = (cast_type *) calloc(n, size);
Beispiel – Summe einer arithmetischen Folge:
#include <stdio.h>
int main() {
int i, *ptr, sum = 0;
ptr = calloc(10, sizeof(int));
if (ptr == NULL) {
printf("Error! memory not allocated.");
exit(0);
}
for (i = 0; i < 10; ++i) {
*(ptr + i) = i;
sum += *(ptr + i);
}
printf("Sum = %d", sum);
free(ptr);
return 0;
}
Ergebnis:
Sum = 45
calloc() vs. malloc()
Wesentliche Unterschiede:
- Initialisierung:
calloc()nullt Speicher;malloc()lässt ihn uninitialisiert (Müllwerte). - Verwendung:
calloc()bevorzugt für Arrays/Strukturen, die Nullwerte brauchen;malloc()simpler, wenn keine Initialisierung nötig. - Performance: Beide performen ähnlich, aber
calloc()kann durch Nullen leicht langsamer sein.
realloc() Funktion
Die realloc()-Funktion ändert die Größe einer existierenden Allokation bei Beibehaltung des Inhalts:
ptr = realloc(ptr, newsize);
Beispiel – String-Puffer erweitern:
#include <stdio.h>
#include <string.h>
int main() {
char *ptr = malloc(10);
strcpy(ptr, "Programming");
ptr = realloc(ptr, 20); // vergrößern
strcat(ptr, " In 'C'");
printf("%s, Address = %u", ptr, ptr);
free(ptr);
return 0;
}
Fällt Reallokation fehl, gibt realloc() NULL zurück und der ursprüngliche Block bleibt gültig.
Dynamische Arrays
Dynamische Arrays erlauben, die Elementanzahl zur Laufzeit wachsen zu lassen – ein gängiges Muster in Algorithmen und Datenstrukturen:
#include <stdio.h>
int main() {
int *arr_dynamic = NULL;
int elements = 2, i;
arr_dynamic = calloc(elements, sizeof(int));
for (i = 0; i < elements; i++) arr_dynamic[i] = i;
for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
elements = 4;
arr_dynamic = realloc(arr_dynamic, elements * sizeof(int));
printf("After realloc\n");
for (i = 2; i < elements; i++) arr_dynamic[i] = i;
for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
free(arr_dynamic);
}
Ergebnis:
arr_dynamic[0]=0 arr_dynamic[1]=1 After realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3
Zusammenfassung
- Dynamischer Speicher erlaubt Allokation und Freigabe von Heap-Speicher zur Laufzeit.
- Nutzen Sie
malloc()für einzelne Blöcke,calloc()für null-initialisierte Arrays. - Prüfen Sie immer auf
NULL, um Allokationsfehler zu erkennen. - Geben Sie Speicher mit
free()frei, um Leaks zu vermeiden. - Ändern Sie Allokationsgröße mit
realloc(), wenn mehr Platz benötigt wird. - Dynamische Arrays sind ein mächtiges Muster für flexible Datenstrukturen.
C Sprache
- ROM, PROM, EPROM und EEPROM verstehen: Design, Programmierung und Identifikation
- C# Grundlagen: Eingabe und Ausgabe Essentials
- C# using-Anweisungen meistern: Importe, Aliase und statische Direktiven
- C++ Speicherverwaltung meistern: Experten-Einsatz von new und delete
- Vier bewährte Muster für benutzerdefinierte Funktionen in C
- Dynamische Speicherallokation in C: malloc, calloc, realloc & free meistern
- C-Standardbibliothek-Funktionen meistern: Praxisleitfaden
- C++ Dynamische Array‑Allokation: Praktischer Leitfaden mit Code‑Beispielen
- C++-Funktionen erklärt: Mit praktischen Code-Beispielen
- C-Funktionen meistern: Struktur, Deklaration & Best Practices