Start > Informatik > C - Kurs > Allocation

Allocation


oder auch Bereitstellen (Allocation) von Speicher mit malloc

Sinn und Zweck

Der Befehl malloc (Kurzform von memory allocation) sorgt dafür, dass man manuell ein Stückchen Speicher reservieren kann.
Warum sollte man Speicher denn selber reservieren, wenn der Rechner das doch bei Variablen auch automatisch macht?
Ganz einfach, manchmal weiß man einfach vorher nicht, wieviel Speicher man braucht. Zum Beispiel kann folgendes passieren: Wir deklarieren ein Array mit 10 Felder, dann will der Benutzer plötzlich aber 50 eingeben. Mit unseren bisherigen Methoden kommen wir nicht weiter, wir brauchen eine Möglichkeit Speicher ganz individuell zu reservieren.

Syntax der Funktion "malloc"

Eigentlich ist malloc garkein Befehl, sondern eine Funktion die aufgerufen wird. Die Funktionsdeklaration sieht (stark vereinfacht) ungefähr so aus:

    void* malloc (int iAnzahlBytes)

Jetzt sollte nach dem gerade besprochenen Kapitel Pointer jedem klar sein, was malloc als Parameter erwartet und was für einen Rückgabewert malloc hat.
Zur Erinnerung: der Parameter gibt an, wieviele Bytes (Einheit in den RAM  gemessen wird) er reservieren soll. void* heißt der Rückgabedatentyp ist auf jeden Fall ein Pointer, aber was für einer?

Bedeutung von void*

Ein void* sorgt dafür, dass nur eine Speicheradresse zurückgegeben wird, ohne das man genau sagt, was für ein Datentyp dazu gehört. Man nennt sowas einen void-Pointer.
Noch genauer werde ich hier nicht darauf eingehen, weil das für unsere Einführung in C viel zu sehr ins Detail geht.

Vorüberlegungen zu Größe eines Datentyps

Am besten lässt es sich am Beispiel von Arrays verdeutlichen. Ein Array wurde ja bereits besprochen.
Wenn nun also ein Array angelegt wird, z.B. mit

    int aiMeins[1000];

dann legt der PC automatisch im Speicher 1000 mal Größe einer integer-Variable im Speicher fest. Jeder Datentyp hat eine bestimmte Größe
  • int 4 Byte
  • float 4 Byte
  • double 8 Byte
  • char 2 Byte
  • usw.
Mit Hilfe von malloc kann man, wie bereits erwähnt, Speicher reservieren. Probieren wir mal unser Array mit Hilfe von malloc anzulegen:

Beispiel mit malloc

    int main(){
       int* piStartadresse;

       piStartadresse = malloc (1000 * 4);
    }

damit wird ein Speicher von 4000 Bytes reserviert. Die Startadresse wird dabei in piStartadresse abgelegt.
Damit man sich nicht merken muss wie groß eine Variable ist gibt es den Befehl

What's the "sizeof" an float?

Das geht ganz einfach:

    printf("Der Datentyp float ist so groß %d", sizeof(float) );

Kombinieren wir nun alles zusammen, kann man einen Speicher mit 1234 integer wie folgt anlegen:

    piStartadresse = malloc (1234 * sizeof (int));

diese Zeile macht nichts anderes als das:

    int piStartadresse[1234];

Wo ist also der Vorteil?

Dazu schauen wir uns folgendes Programm einmal an:

    int main(){
       int iMax;
       int* piArray;
       printf("Wie groß hätten Sie es denn gerne?");
       scanf("%d", iMax);
       fflush(stdin);
       piArray = malloc (iMax * sizeof(int));
    }

Wie man schön sehen kann, wird hier ein Array erst dann angelegt, wenn der Benutzer festgelegt hat, wie groß es sein soll. Das ist der entscheidende Vorteil. Man braucht also vorher nicht mehr festlegen, wie groß ein Array sein muss.
Nachteil: Man muss mit Pointer arbeiten.

Wie kann ich auf ein Array zugreifen, wenn ich nur die Startadresse pi... habe?

Ganz einfach, wie bei normalen Arrays:

    piArray[Index] = ...

Zusammenfassung

Wir lernen:
  • malloc kann beliebige Speichergrößen reservieren
  • Rückgabewert ist eine Speicheradresse
  • mit malloc können Arrays angelegt werden, deren Größe variabel ist
Vorsicht: wie gerade gesagt, kann man mit malloc Speicher reservieren. Damit kann man aber auch sein System ganz schnell abschießen, wenn man "aus Versehen" zuviel Speicher reserviert. Dann hat man nämlich plötzlich keinen mehr!

Jetzt gibts zum Abschluss noch ein technisches Schmankerl, wie piArray[Index] genau funktioniert, dazu braucht man nämlich ...

Pointer-Arithmetik

So jetzt wird ein wenig hakelig und etwas anspruchsvoller. Fangen wir mit einem konkreten Beispiel an:

        piArray[5]

Der PC liest an dieser Stelle eigentlich folgendes:

    * ( piArray + 5 * sizeof ( int ))

Was hier passiert ist eigentlich ganz einfach. Erstmal gilt Klammern gehen immer vor, d.h. er rechnet zuerst das in den Klammern aus:

       piArray + 5 * sizeof (int)

in piArray steht ja eine physikalische Speicheradresse (deswegen ja p...) dann wird dazu 20 addiert. (sizeof(int) ist ja 4 und 4*5=20). Mit anderen Worten, der Rechner fängt bei der Speicheradresse piArray an zu zählen und geht 20 Bytes weiter. Dann kommt

    * (eine Speicheradresse)

das ist der Dereferenzierungsoperator, der den Inhalt an dieser Speicherstelle wiedergibt.

hier schliesst sich also der Kreis mit Pointern und Arrays und malloc. Irgendwie gehört alles zusammen.

Infoblätter und Arbeitsblätter

Übungen zu malloc und Arrays
Info: Auf diesem Arbeitsblatt gibt es ein paar Übungen zum Erstellen von Arrays mit Hilfe von malloc. Ebenfalls sind ein paar "Bug"-Suche Aufgaben enthalten.
Ticker
Last update:
June 29. 2017 19:48:11