Funktionen für Felder und Zeichenketten¶
malloc()
und calloc()
– Dynamische Speicherreservierung¶
Soll die Größe eines Feldes erst zur Laufzeit bestimmt werden, so ermöglichen es
die Funktionen malloc()
und calloc()
aus der Standard-Bibliothek
stdlib.h, nach Möglichkeit ein entsprechend großes Stück an
freiem Speicherplatz („memory“) zu finden und für das Feld zu reservieren
(„allocate“).
Der Speicher eines Programms setzt sich allgemein zusammen aus einem Teil namens
„Stack“, der für statische Variablen reserviert ist, und einem dynamischen Teil
namens „Heap“, auf den mittels malloc()
oder calloc()
zugegriffen werden
kann.
Bei der Verwendung dieser Funktionen kann valgrind als „Debugger“ für dynamischen Speicherplatz eingesetzt werden.
Die Funktion malloc()
Als Ergebnis gibt die Funktion malloc()
einen Zeiger auf die nutzbare
Speicheradresse zurück, oder NULL
, falls keine Speicherreservierung möglich
war. Bei jeder neuen Speicherreservierung sollte der Rückgabewert geprüft und
gegebenenfalls eine Fehlermeldung ausgegeben werden. Im erfolgreichen Fall hat
der zurück gegebene Zeiger den Typ void *
und wird üblicherweise vom
Programmierer mittels des cast
-Operators in einen Zeiger vom gewünschten Typ
umgewandelt.
Um beispielsweise einen dynamischen Speicherplatz für ein Array mit
int
-Werten zu erhalten, kann man folgendes eingeben:
numbers = (int *) malloc(50 * sizeof (int));
An die Funktion malloc()
wird allgemein die zu reservierende Speichergröße
in Bytes als Argument übergeben; für beispielsweise Werte vom
Datentyp int
ist damit auch das Fünfzigfache der Größe dieses Datentyps
nötig. Der Rückgabewert von malloc()
, nämlich void *
, wird mit Hilfe des
Casts (int *)
in einen Zeiger auf int
umgewandelt.
Wird der Speicher nicht mehr benötigt, so muss er manuell mittels free()
wieder freigegeben werden. Als Argument wird dabei der Name des variablen
Speichers angegeben, also beispielsweise free(numbers)
. In C gibt es keinen
„Garbage Collector“, der nicht mehr benötigte Speicherbereiche automatisch
wieder freigibt; es ist also Aufgabe des Programmierers dafür zu sorgen, dass
Speicher nach dem Gebrauch wieder freigegeben wird und somit kein Speicherleck
entsteht.
Die Funktion calloc()
Neben der Funktion malloc()
gibt es in der Standardbibliothek stdlib.h eine weitere Funktion zur dynamischen Speicherreservierung namens
calloc()
. Beim Aufruf dieser Funktion wird als erstes Argument die Anzahl
der benötigten Variablen, als zweites Argument die Größe einer einzelnen
Variablen in Bytes angegeben. Bei einer erfolgreichen Reservierung wird, wie bei
malloc()
, ein void *
-Zeiger auf den reservierten Speicher zurückgegeben,
andernfalls NULL
. Der Unterschied zwischen malloc()
und calloc()
liegt darin, dass calloc()
alle Bits im Speicherbereich auf 0
setzt und
dadurch sicherstellt, dass zuvor mit free()
freigegebene Daten zufällig
weiterverarbeitet werden.
Auch bei der Verwendung von calloc()
muss Speicher, der nicht mehr benötigt
wird, manuell mittels free()
wieder freigegeben werden.
Die Funktion realloc()
Mit der Funktion realloc()
kann ein mit malloc()
oder calloc()
reservierter Speicherbereich nachträglich in seiner Größe verändert werden.
Als erstes Argument gibt man bei realloc()
einen Zeiger auf einen bereits
existierenden dynamischen Speicherbereich an, als zweites die gewünschte neue
Größe des Speicherbereichs. Kann der angeforderte Speicher nicht an der
bisherigen Adresse angelegt werden, weil dort kein ausreichend großer
zusammenhängender Speicherbereich mehr frei ist, dann verschiebt realloc()
den vorhandenen Speicherbereich an eine andere Stelle im Speicher, an der noch
genügend Speicher frei ist.
numbers = (int *) realloc(numbers, 100 * sizeof (int));
Als Ergebnis gibt die Funktion realloc()
ebenfalls einen void *
-Zeiger
auf den reservierten Speicherbereich zurück, wenn die Speicherreservierung
erfolgreich war, andernfalls NULL
. Übergibt man an realloc()
einen
NULL
-Pointer als Adresse, so ist realloc()
mit malloc()
identisch
und gibt einen Zeiger auf einen neu erstellten dynamischen Speicherbereich
zurück.
memcmp()
und strcmp()
– Vergleiche von Feldern¶
In C kann man den Inhalt zweier Felder nicht direkt vergleichen, es kann hierfür
also nicht array_1 == array_2
geschrieben werden. Bei diesem Test würden
lediglich, da der Name eines Feldes auf das erste im Feld gespeicherte Element
verweist, die Speicheradressen zweier Variablen verglichen werden, jedoch nicht
deren Inhalt.
Für einen inhaltlichen Vergleich müssen alle Einzelelemente der Felder miteinander verglichen werden. Dies kann automatisch mit der Funktion memcmp() aus der Standardbibliothek string.h durchgeführt werden. Bei identischen Feldern wird der Wert als Ergebnis zurückgegeben. Stößt die Funktion im ersten Feld auf einen Wert, der größer ist als im zu vergleichenden Feld, so wird ein positiver Wert zurückgegeben, im umgekehrten Fall ein negativer Wert .
Handelt es sich bei den Feldern um Zeichenketten, so sollte anstelle von
memcmp()
bevorzugt die Funktion strcmp()
verwendet werden. Diese prüft
ebenfalls Zeichen für Zeichen, ob die beiden angegebenen Zeichenketten
übereinstimmen. Anders als bei memcmp()
wird jedoch das Überprüfen der
Feldinhalte beendet, sobald das String-Ende-Zeichen \0
erreicht wird.
Mögliche Inhalte der Felder hinter diesem Zeichen werden somit nicht verglichen.
memcpy()
und strcpy()
– Kopieren von Feldern¶
Der Funktion strcpy()
wird als erstes Argument der Name des Zielstrings, als
zweites Argument eine dorthin zu kopierende Zeichenkette übergeben:
char target_string[50];
strcpy(target_string, "Hallo Welt!");
puts(target_string);
// Ergebnis: "Hallo Welt!"
Der Zielstring wird von strcpy()
automatisch mit dem
Zeichenkette-Ende-Zeichen '\0'
abgeschlossen. Wichtig ist zu beachten, dass
strcpy()
nicht prüft, ob der Zielstring ausreichend groß ist; reicht der
Platz dort nicht aus, werden die Bytes einer anschließend im Speicher abgelegten
Variablen überschrieben, was unvorhersehbare Fehler mit sich bringen kann. Als
Programmierer muss man somit entweder selbst darauf achten, dass nicht
Zielstring ausreichend groß ist, oder die Funktion strncpy()
verwenden, welcher als drittes Argument die Anzahl der zu kopierenden
Zeichen übergeben wird.
strcat()
– Verknüpfen von Zeichenketten¶
Der Funktion strcat()
wird als erstes Argument der Name des Zielstrings, als
zweites Argument eine dort anzufügenden Zeichenkette übergeben:
char target_string[50];
strcpy(target_string, "Hallo Welt!");;
strcat(target_string, " Auf Wiedersehen!");
puts(target_string);
// Ergebnis: "Hallo Welt! Auf Wiedersehen!"
strcat()
überschreibt automatisch das Zeichenkette-Ende-Zeichen '\0'
des Zielstring mit dem ersten Zeichen des anzuhängenden Strings und schließt
nach dem Anfügen der restlichen Zeichen den Zielstring wiederum mit '\0'
ab.
Ebenso wie bei strcpy()
muss auch bei Verwendung von strcat()
auf einen
ausreichend grossen Zielstring geachtet werden. Als Alternativ kann die Funktion
strncat()
verwendet werden, der als drittes Argument eine Anzahl
an anzuhängenden Zeichen übergeben wird.