ein Kapitel zurück                                           ein Kapitel weiter

Kommen wir zu weiteren Funktionen zum dynamischen Anfordern von Speicherplatz. Die Funktion 'malloc()' kennen wir ja bereits schon. Nun sind in der Headerdatei <stdlib.h> noch folgende 2 Funktionen dafür vorhanden...

void *calloc(size_t anzahl, size_t groesse);
void *realloc(void *zgr, size_t neuegroesse);


Die Funktion 'calloc()' ist der Funktion 'malloc()' ähnlich. Nur das es bei der Funktion 'calloc()' nicht einen, sondern 2 Parameter gibt. Im Gegensatz zu 'malloc()' können sie bei 'calloc()' noch die 'anzahl' von Datenobjekten angeben die sie allokieren wollen.
Beispiel wir wollen für 100 Datenobjekte vom Typ 'int' Speicherplatz allokieren....

int *zahlen;

zahlen=(int *)calloc(100,sizof(int));


Der zweite Unterschied zu 'malloc()' das der allokierte Speicherbereich automatisch mit 0 initialisiert wird bei 'calloc()'. Bei 'malloc()' besitzt ja der reservierte Speicherplatz zu Beginn einen undefinierten Wert.
Da 'calloc()' außer den beiden eben genannten Unterschiede sonst im Prinzip genauso funktioniert wie 'malloc()' will ich es dabei mit 'calloc()' belassen.

Interessanter ist da schon die Speicherreservierung die uns die Funktion 'realloc()' bietet. Damit ist es uns nun wirklich möglich im während dem laufenden Programm soviel Speicher zu reservieren wie wir benötigen. Und das für, und vor allem auch, für Arrays.
Mit 'realloc()' sind wir nun in der Lage Dynamische Arrays zu programmieren. Die Anfangsadresse unserem 'dynamischen Array' ist die auf der unser - Zeiger (zgr) zeigt. Der Parameter 'neuegroesse' dient dazu einen berreits zuvor allokierten Speicherplatz auf 'neuegrosse' Bytes zu vergrößern. Apropos, mit 'realloc()' ist es auch möglich den Speicherplatz zu verkleinern. Es wird einfach der hintere Teil freigegeben während der fordere Teil unverändert bleibt. Bei einer Vergrößerung des Speicherplatzes mit 'realloc()' behält der vordere Teil auf jeden Fall seinen Wert und der hintere Teil wird einfach hinten angehängt. Dieser angehängte Wert ist aber wie bei 'malloc()' undefiniert und nicht wie bei 'calloc()' mit 0 initialisiert. Nun ein kleines Beispiel wie man ein Array dynamische machen kann.....

/*Download:call.c*/
#include <stdio.h>
#include <stdlib.h>


int main()
{
int n=0,max=10,z,i,*zahlen=NULL;

/*Wir reservieren Speicher für 10 int Werte mit calloc*/
if((zahlen=(int *)calloc(max, sizeof(int)))==NULL)
{
fprintf(stderr,".....Speichplatzmangel!!!!!\n");
exit(0);
}
printf("Zahlen eingeben --- Beenden mit 0\n");

while(1)
{
printf("Zahl (%d) eingeben : ",n+1);
scanf("%d",&z);
if(z==0)
break;

/*Reservierung während der Laufzeit des Programms mit realloc*/
if(n>=max)
{
max+=max;
if((zahlen=(int *)realloc(zahlen,max * sizeof(int))) ==NULL)
{
fprintf(stderr,".......Speicherplatzmangel!!!\n");
exit(1);
}
printf("Speicherplatz reserviert (%d Bytes)\n",sizeof(int)*max);
}

zahlen[n++]=z;
}

printf("Folgende Zahlen wurden eingegeben ->\n\n");
for(i=0;i<n;i++)
printf("%d ",zahlen[i]);

free(zahlen);
return 0;
}

Sicherlich hätten wir unseren Speicher auch einzeln Allokieren können. Nur bedenken sie bitte falls sie das vorhaben, das unsere Funktion 'realloc()' alten Speicher in einen größeren Speicherbereich umkopieren muss. In diesem Beispiel habe ich den Speicherplatz nach jedem erneuten allozieren mit 'calloc()' gleich verdoppelt (max+=max) was natürlich auch nicht ideal ist. Es kommt eben auf Ihr Programm an, wie viele Datenobjekte eines Typen das sie benötigen. Schreiben sie zum Beispiel ein Programm bei wo sie täglich bis zu 500 double - Zahlen eingeben wäre doch am sinnvollsten nach allen 500 double - Werten neuen Speicher zu allozieren. Somit müsste unser Programm nur einmal am Tag neuen Speicher allozieren.

Ein weiteres Beispiel zum dynamischen Anfordern von Speicher ist die Funktion.....

void *alloca(size_t size);

...bei Linux/Unix ebenfalls in der Headerdatei <stdlib.h> liegt. Unter MS-DOS/WIN könnte sich diese Funktion auch in der Headerdatei <malloc.h> liegen.
'alloca()' können sie auch wieder mit 'malloc()' vergleichen. Nur das 'alloca()' den Speicherplatz nicht vom Heap sondern vom Stack anfordert.

Stack Im Stack werden alle lokale Variablen einer Funktion abgelegt, jedes Mal wenn diese aufgerufen wird. Mehr dazu gibt es in dem Kapitel der Rekursionen.
Heap Wird während des laufenden Prozesses mit 'malloc(),calloc(),realloc()' neuer (dynamisch) Speicher angefordert, so wird dieser in seinem Heap-Bereich zugeteilt


'alloca()' hat den Vorteil das sie den Speicherplatz nicht extra mit 'free()' freigeben brauchen, da dieser automatisch beim verlassen der Funktion freigegeben wird.
'alloca()' vergössert außerdem den stack frame (Stackbereich) der aktuellen Funktion. Und das ist auch der Grund weshalb 'alloca()' nicht überall verfügbar ist, da es mit manchen Systemen nicht möglich ist den Stackbereich zu vergrößern.
Da die Funktion 'alloca()' genauso so eingesetzt wird wie 'malloc()' will ich hier auf ein Beispiel verzichten.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf