next up previous contents index
Nächste Seite: 6.5 Zeiger auf Strukturen Aufwärts: 6. Zeiger Vorherige Seite: 6.3 Zeiger und Felder   Inhalt   Index


6.4 Dynamische Felder mittels Zeigervariablen

Bisher verwies ein Zeiger auf bereits bereitgestellten (allocated) Speicher für eine einfache Variable, Struktur, Feld. Für Zeiger kann aber auch ein zum Typ dazugehöriger Speicherbereich dynamisch allokiert werden. Hierzu benutzt man das neue Schlüsselwort new . Der damit allokierte Speicher kann mittels delete wieder freigegeben werden. (siehe Ex641.cc)

//	Dynamic variable and  
//	Dynamic array 1D
#include <iostream.h>
main()
{
  int     n,i;
  double  *px, *pvar;
  
  cout << "  Eingabe n : ";  cin >> n;
  
  px = new double[n];           //  Allocate array

// 		initialize array
  for (i = 0; i < n; i++ )
   {
     px[i] = (i+1)*(i+1);
   } 
      
//		output x;
  for ( i = 0; i < n; i++)
   {
     cout << "  " << px[i] << endl;
   }
  
  delete [] px;                    // Deallocate array
  
   pvar = new double;              // Allocate variable
  *pvar = 3.5 * n;
  delete pvar;                     // Deallocate variable
}

Die Anweisung px = new double[n]; allokiert n*sizeof(double) Byte für den Zeiger px. Danach kann das dynamische Feld px wie ein statisches Feld behandelt werden. Allerdings nutzen dynamische Felder den vorhandenen Speicherplatz besser, da dieser mit dem delete-Befehl freigegeben und anderweitig wieder genutzt werden kann.

Achtung: Obige dynamische Feldvereinbarung ist nur für C++ gültig. In C müssen andere Befehle verwendet werden - hier die Unterschiede. (siehe Ex640.c)

C++         C
          #include <malloc.h>
px = new double[n];         px = (double*) malloc(n*sizeof(double));
delete [] px;         free(px);

Ein zweidimensionales dynamisches Feld läßt sich einerseits durch ein eindimensionales dynamisches Feld darstellen (analog zu Variante 2 in § 5.1.2) als auch durch einen Zeiger auf ein Feld von Zeigern. Dies sieht für eine Matrix mit n Zeilen und m Spalten wie folgt aus. (siehe Ex642.cc)

//	Dynamic array 2D
#include <iostream.h>
main()
{
  int     n,m,i,j;
  double  **b;          // pointer at pointers at double
  
  cout << "  Eingabe Zeilen  n : ";  cin >> n;
  cout << "  Eingabe Spalten m : ";  cin >> m;
  
  b = new (double* [n]);      // Allocate row pointers
  for (i = 0; i < n; i++)
   {
     b[i] = new double[m];    // Allocate rows
   }
   
  for (i = 0; i < n; i++ )    // initialize b
   {
     for (j = 0; j < m; j++)
      {
        b[i][j] = (i+1)*(j+1);
      }
   } 
...
  for (i = n-1; i >= 0; i--)
   {
     delete []  b[i];            //  Deallocate rows
   }
  delete [] b;                   //  Deallocate row pointers
}

Zuerst muß der Zeiger auf die Zeilenpointer allokiert werden, erst danach kann der Speicher für die einzelnen Zeilen angefordert werden. Beim Deallokieren des Speichers müssen ebenfalls alle Zeilen wieder freigegeben werden. Für den Fall n = 3 und m = 4 veranschaulicht das Bild die Ablage der Daten im Speicher.

\begin{center}\vbox{\input{kap640.pstex_t}
}\end{center}

Achtung: Es gibt keine Garantie, daß die einzelnen Zeilen der Matrix hintereinander im Speicher angeordnet sind. Somit unterscheidet sich die Speicherung des dynamischen 2D-Feldes von der Speicherung des statischen 2D-Feldes obwohl die Syntax des Elementzugriffes b[i][j] identisch ist. Dafür ist diese Matrixspeicherung flexibler, da die Zeilen auch unterschiedliche Längen haben dürfen (dünnbesetzte Matrizen oder Matrizen mit Profil).

Zeiger können wiederum in Strukturen oder allgemeinen Typen auftreten. Hierbei ist allerdings größtmögliche Sorgfalt in der Verwendung der dynamischen Felder geboten, da für statische Variablen ansonsten unkritische Operationen plötzlich zu mirakulösem Programmverhalten führen können.

//	Demonstration of   w r o n g   code 
//		wrt. copying a structure with pointers
#include <iostream.h>
#include <strings.h>			// strcpy, strlen

struct Student2
  {
    long long int matrikel;
              int skz;
              char *pname, *pvorname;	// Pointers in structure
  };

main()
{
 Student2 arni, robbi;
 char     tmp[80];           // temp. input string
 
 cin  >> tmp;                // read vorname
//		Allocate memory for arni.pvorname
 arni.pvorname = new char[strlen(tmp)+1];// Don't forget "+1
 strcpy(arni.pvorname,tmp);		 // and copy input on it

// the same with the remaining data on arni
 ...
//	rough and  w r o n g  copying
 robbi = arni;
//	Point (A)
 ...
 delete [] arni.pvorname;  // deallocate
//	Point (B)
 ...
//                    Let us allocate some tiny dynamical array
 char *tiny;
 tiny = new char [5];
 strcpy(tiny,"tiny");
//	Point (C)
...
}
(siehe Ex643-warning.cc)

Wie sieht der Datenspeicher zu den Zeitpunkten (A), (B) und (C) aus?

2389


next up previous contents index
Nächste Seite: 6.5 Zeiger auf Strukturen Aufwärts: 6. Zeiger Vorherige Seite: 6.3 Zeiger und Felder   Inhalt   Index
Gundolf Haase 2004-01-15