[Inhalt][0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17]

Teil 10 : Die dynamischen Felder in C

Was machte man bisher, wenn man nicht wußte, wieviel Elemente ein Feld haben soll ? Man erzeugte immer ein Feld mit der maximalen Anzahl der Elemente. Das dieses sehr zu Lasten des Arbeitsspeichers geht kann man sich vorstellen. Was tun wenn man nun mit seinem kostbaren Speicher haushalten will ? Man fängt an dynamisch zu programmieren, was nichts anderes bedeutet, als das man sich nur den Speicher nimmt, den man gerade benötigt.
 
 
Speicheranforderung

Zu beginn müssen wir im Kopf eine Include-Datei einfügen, welche die benötigten Vereinbarungen und Module für die Speicherbelegung enthält
 

#include <stdlib.h>

Nehmen wir an, wir benötigen ein Feld mit einer veränderlichen Größe. Was wir nun benötigen ist eine Anzahl der Elemente, die wir anfordern und die Größe der Einzelelemente, damit wir dem Rechner mitteilen können, wieviel Speicher wir für unsere Zwecke benutzen wollen. Die Speicheranforderung erfolg mittels
 

Variablentyp *feld;
:
feld = malloc (Anzahl * sizeof ( Variablentyp ));

Es wird ein Feld angefordert, welches aus Daten des Typs Variablentyp besteht. Es kann hier z.B. eine Struktur als Element angefordert werden. Von der Funktion malloc wird ein Zeiger auf das erste Feldelement zurückgegeben. Als Rückgabewert erhalten wir einen Zeiger auf das erste Element des so initialsierten Feldes. Dumm ist es, wenn man mehr Speicher anfordert als zur Verfügung steht. Da man als Programmierer nicht alles wissen kann lassen wir uns natürlich auch gleich anzeigen, wenn die Speicheranforderung fehlschlug. Wird als Rückgabewert NULL geliefert, ist etwas schiefgelaufen. Dies sollte man immer bei der Speicheranforderung abfragen! Als Argument für malloc ist der Speicher in Bytes anzugeben, welcher angefordert wird. Nun kann man von faulen, ok - effizient ist ein besseres Wort :) , Programmierern nicht verlangen die Bytes abzuzählen, die ein Element beansprucht.Dafür gibt es eine tolle Funktion namens sizeof die das für uns erledigt.
 

int bytes;
:
bytes = sizeof ( Variablentyp );

Im Beispiel ist der Variablentyp durch den Elemtentyp, z.B. double oder auch durch eine Struktur zu ersetzen. Als Rückgabe erhält man die Anzahl, die der Variablentyp belegt als Integer.
Wenn man nun diesen Wert mit der Elementenanzahl multipliziert, erhalten wir den Speicher in Bytes, die unser Feld beansprucht.
 

:
int bytes;
int Feldgroesze = 5;

/*

    Nun berechnen wir, wieviel Speicher ein Feld
    mit 5 double-Elementen benötigt
*/

bytes = Feldgroesze * sizeof ( double );
:


 
 
Speicherfreigabe

Was macht man mit Dingen, die man nicht mehr benötig ? Man entsorgt sie. Wenn man nun ein Feld wieder freigeben möchte, so sagt man ihm einfach mittels
 

Variablentyp *feld;
:
free ( feld );

Das er den Speicher auf den der übergebene Zeiger zeigt wieder freigegeben wird. In einem Programm müßte also folgendes einfügen um Speicher zu belegen und wieder freizugeben.
 

Variablentyp *feld;
:
/* Speicheranforderung */
feld = malloc (Anzahl * sizeof ( Variablentyp ));
:
/* Speicherfreigabe */
free (feld);
:

 
 
Beispielprogramm

Ein komplettes Minimalprogramm für eine Speicheranforderung und -freigabe kann wie folgt aussehen:
 
 

/* wichtig! Für malloc stdlib.h einbinden */ 

#include <stdio.h> 
#include <stdlib.h> 

void main (void

    int feldgroesze; 
    int *feld;
    /* Feldgröße erfragen */ 

    printf ("\nBitte geben sie die Feldgroesse an : "); 
    scanf ("%d",&feldgroesze);
    /* 

      Speicher anfordern durch 
      feld = malloc (feldgroesze * Größe des Einzelelements)
    */ 

    feld = malloc (feldgroesze * sizeof (int));
    /* Abfrage, ob ein Fehler auftrat */ 

    if (feld == NULL) 

      printf ("\nZu wenig Speicher!\n");

    else
      printf ("\nOk, Speicher wurde angefordert\n");
    }
    /* 
      Hier nun ein Programm stehen, welches den Speicher, den 
      wir angefordert haben benutzt.
    */ 

    /* freigeben des Speichers nach getaner Arbeit */ 

    free (feld); 
    printf ("\nDer Speicher wurde wieder freigegeben!\n"); 


}

Beim austesten kann dann der folgende Bildschirm entstehen:

Screenshot des ausgeführten Programms

Wie können wir den nun so gewonnenen Speicherplatz benützen ? Hier ein kleines Beispiel eines Programms aus Bereich der Naturwissenschaften, mit dem wir ein paar Meßergebnisse eines Versuches einlesen können und daraus den Durchschnitt bilden. Zur Übung könnte man das Programm so erweitern, das die Abstände zwischen den einzelnen Werten ausgegeben werden.
 

/* wichtig! Für malloc stdlib.h einbinden */
/*
ges  ist die Gesamtsumme des Feldes
ist eine Hilfsvariable für Schleifen
feldgroesze  ist die Anzahl der Elemente im erzeugten Feld
feld  ist das erzeugte Feld
*/
#include <stdio.h> 
#include <stdlib.h> 

void main (void
{

float ges = 0;
int i;
float *feld;
int feldgroesze;

/* Feldgröße erfragen */ 
printf ("\nBitte geben sie die Feldgroesse an : "); 
scanf ("%d",&feldgroesze);

/* 

Speicher anfordern durch 
feld = malloc (feldgroesze * Größe des Einzelelements)
*/ 
feld = malloc (feldgroesze * sizeof (float));

/* Abfrage, ob ein Fehler auftrat */ 
if (feld == NULL

printf ("\nZu wenig Speicher!\n");

else
printf ("\nOk, Speicher wurde angefordert\n");
/* 
Hier nun ein Programm stehen, welches den Speicher, den 
wir angefordert haben benutzt.
*/ 
ges =  0;
for ( i=0; i<feldgroesze; i++)
{
printf ("\nData : ");
scanf ("%f",(feld+i));
ges += *(feld+i);
}
printf("\n\nDurchschnittt : %f\n", ges/feldgroesze);

/* freigeben des Speichers nach getaner Arbeit */ 
free (feld); 
printf ("\nDer Speicher wurde wieder freigegeben!\n"); 

}
}

Ein Beispielablauf würde dann so aussehen

Screenshot des ausgeführten Programms

Wie wir sehen, können wir über die Zeiger auf die einzelnen Feldinhalte zugreifen und diese so lesen und schreiben. Bitte immer darauf achten, das die Indizes immer bei 0 anfangen. Zur Übung kann man ein Programm erstellen, welches eine beliebige Anzahl von Namen einliest und diese wieder darstellt.

[Inhalt][0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17]