peace software
  Berndt Wischnewski  Richard-Wagner-Str. 49  10585 Berlin 
  Tel.: 030 - 3429075  FAX : 030 34704037  email: webmaster@peacesoftware.de  Ust-ID: DE135577379 
<= Previous

 

C Kurs - also ein Array ist wenn man viele Variablen...

1. Syntax

Wie wir Variablen deklarieren wissen wir noch
     int x;
was aber wenn wir 100 Variablen brauchen, oder vielleicht 100000? Es wäre irgendwie unpraktisch jetzt zu schreiben:
int x1, x2, x3, x4, x5,   ....   x98, x99, x100;
Die Lösung für diese Probleme sind Arrays (schwierig ins deutsche zu übersetzen, vielleicht indizierter Variablenblock?).

Die Syntax für die Deklaration eines Array ist recht einfach:
     int x_array[100];
zuerst kommt der Typ der Variablen, z.B. int, dann folgt der Name des Array, danach in eckigen Klammern [ ] die Größe des Arrays, also die gewünschte Anzahl der Array-Elemente.

Will man auf ein Element des Arrays zugreifen, so gibt man einfach den Index des Elementes in eckigen Klammern an:
     x_array[42] = 987; // in das 43. Element des Arrays wird 987 geschrieben
     meine_variable = x_array[66];
//das 67. Element wird gelesen und der Variablen meine_variable zugewiesen

In C ebenso wie in auf C basierenden Programmiersprachen(z.B. Java, Perl usw) sind die Arrays 'zero based indexed', d.h. das erste Element des Arrays hat den Index Null, das bedeutet deklariert man in seinem Programm int y[50]; dann erhält man ein Array mit den Indexzahlen y[0] bis y[49]. Dies ist im ersten Moment etwas gewöhnungsbedürftig, aber auch nicht unpraktisch.

Man kann Array gleich bei der Deklaration in einem Block mit geschweiften Klammern initialisieren, z.B so:
      int arr1[5] = {1, 2, 3, 4, 5};

 

2. Speicherstruktur eines Arrays

Sie erinnern sich das eine Variable ein Stück Speicherplatz im Hauptspeicher Ihres Computers ist. Bei der Deklaration eines Arrays wird der Compiler angewiesen n-mal nacheinander den Speicherplatz für diese Variable zu reservieren. Man hat anschließen einen zusammenhängen Block von Slots des Variablentyps im Hauptspeicher stehen, der für die Array Elemente reserviert ist. Folgende Abbildung sollte dies veranschaulichen:

 

Speicherstruktur eines Arrays

Wichtig: viele Compiler initialisieren den Array bei er Deklaration gleich mit Nullen, dies ist sehr praktisch, leider tun andere Compiler dies nicht. In den einzelnen Slots steht dann das drin, was schon vorher drinstand also garbage (Müll). Wenn man sich nicht völlig sicher ist, das die Software an der man gerade sitzt, niemals von jemand anderem weiterentwickelt wird, sollte man den Array (oder das Array???, der Berliner würde sagen 'dem Array') in einer Schleife initialisieren.

 

 

3. Arraygrenzen

Wichtig: C überprüft die Arraygrenzen nicht.
z.B.

int x[100], index;

index = -25;
x[1000] = 42; // -> BUMM
// oder vielleicht
x[index] = 0; // -> BANG

wird anstandslos kompiliert obwohl der Array eigentlich nur 100 integer Elemente hat. Man bekommt keine Warnung und nichts. Führt man das Programm jetzt aus wird in die Speicheradresse die 1000 * integer von der Arraystartadresse entfernt ist, 42, eingefügt. Dies kann zu allen möglichen führen, z.B. das Programm stürzt ab. Unter alten Betriebssystemen ohne Speicherschutz, konnte man auf diese Weise sogar den ganzen Rechner zum Absturz bringen. Oder in einem anderen Array taucht plötzlich ein unsinniger Wert auf, oder schlimmer, der Wert ist nicht unsinnig sondern sogar plausibel. Oder an dieser Stelle steht vielleicht zufällig unbenutzter, freier Speicherplatz, dann merkt man von dem Fehler erstmal nichts.

Der zweite Teil des Beispiels, x[index] = 0; soll zum einen verdeutlichen, das man als Index natürlich eine integer Variable einsetzen kann, welche dann auch einen unsinnigen Wert, hier -25, enthalten kann.

 

4. mehrdimensionale Array

Wem ein eindimensionaler Array nicht reicht, der kann sich auch mehrdimensionale Arrays deklarieren:

// Deklarationen
int x[100][50]; // zweidimensionaler Array - etwa 20 Kilobyte; 4 Bytes pro int * 100 * 50
float y[100][50][100]; // dreidimensionaler Array - etwa 2 Megabyte; 4 Bytes pro float * 100 * 50 * 100
char z[100][50][100][100]; // vierdimensionaler Array - etwa 50 Megabyte -> Vorsicht, so langsam wirds sehr groß

// Zuweisungen
x[1][2] = 666;
y[1][2][3] = 777.77;
z [1][2][3][4] = 'a';

Das sieht auch aller recht klar und verständlich aus oder? Man gibt einfach in weiteren eckigen Klammer die gewünschte Größe der nächsten Dimension an.

Wie viele Dimensionen man anlegen kann ist abhängig vom Compiler und steht irgendwo in dessen Handbuch, bei mir waren es bis jetzt immer ausreichend genug (ich hatte auch noch nie mehr als 3).

Die maximale Größe des Speicherplatzes für einen Array ist auch nicht unendlich.Die natürliche Grenze ist der maximal zur Verfügung stehende freie Speicherplatz, mehr ist halt nicht da. Unter alten Compilern auf älteren Betriebssystemen (MSDOS) gab es hier auch andere Einschränkungen, 16 Kilobyte, 32 Kilobyte 64 Kilobyte durften je nach Speichermodell nicht überschritten werden.

Folgende Abbildung soll veranschaulichen wie ein mehrdimensionaler Array im Hauptspeicher angelegt wird:

mehrdimensionaler Array im Hauptspeicher

 

 

 

5. Array an eine Funktion übergeben

Einen eindimensionalen Array an eine Funktion zu übergeben ist völlig simpel, man schreibt in den Funktionskopf seine Arrayvariable, und im innern der Funktion benutzt man ihn einfach. Meist ist es schlau, noch die Größe des Arrays, die Anzahl seiner Elemente, mit zu übergeben. Dann kann man auch verschieden große Arrays mit ein und der selben Funktion bearbeiten. Natürlich gilt auch hier, der Compiler überprüft die Arraygrenzen nicht, deshalb braucht man die Größe des Arrays meistens sowieso, es sei denn die Größe ist immer gleich und man kennt sie.

Hier kommt auch schon ein Beispiel:

#include <stdio.h>

int main (void)
{
   int i, arr[5] = {1,2,3,4,5}; // Array deklarieren und gleich initialisieren, so geht das auch

   for(i = 0; i < 5; i++) // for Schleife, kommt im nächsten Kapitel
   {
      printf("arr[%d]: %d\n", i, arr[i]); // Array anzeigen
   }

   ReadWriteIntoArray(5, arr); // Funktion aufrufen

   for(i = 0; i < 5; i++) // for Schleife, kommt im nächsten Kapitel
   {
       printf("arr[%d]: %d\n", i, arr[i]); // Array nochmal anzeigen
   }
   return 0;
}

void ReadWriteIntoArray(int arraysize, int arrvar[]) // Funktion in die zwei Variablen hineingehen
                                                                                     // erstens die Arraygröße und zweitens der Array selber
{
   int i;

   for(i = 0; i < arraysize; i++) // for Schleife, kommt im nächsten Kapitel
   {
      printf("inside: arr[%d]: %d\n", i, arrvar[i]); // Array ausgeben
      arrvar[i]++; // Arrayelement wird verändert
   }
}

 

Komplizierter wird es, wenn man einen mehrdimensionalen Array an eine Funktion übergeben will. Hier muß man zumindestens die Größe der 2. bis ntnen Dimension angeben, sonst weiß der Compiler nicht, wie er den Speicher organisieren soll. Die der 1. Arraydimension darf man natürlich auch angeben, wenn man sie schon vorher weiß. Sehen Sie sich bitte noch mal die Abbildung des mehrdimensionalen Array an und überlegen, warum man dem Compiler die Größe der 2. und aller weiteren Dimensionen mitteilen muß.

Hier ein Beispielprogramm:

#include <stdio.h>

int main (int argc, const char *argv[])
{
   int i, j;
   int arr[2][3]; // Array wird definiert, zwei Dimensionen
   arr[0][0] = 1; // Array wird initialisiert
   arr[0][1] = 2;
   arr[0][2] = 3;
   arr[1][0] = 11;
   arr[1][1] = 12;
   arr[1][2] = 13;

   for(i = 0; i < 2; i++) // for Schleife, kommt im nächsten Kapitel
      for(j = 0; j < 3; j++)
          printf("arr[%d]: %d\n", i, arr[i]); // Array anzeigen
   

   ReadWriteIntoArray(2, arr); // Funktion aufrufen

   for(i = 0; i < 2; i++) // for Schleife, kommt im nächsten Kapitel
      for(j = 0; j < 3; j++)
          printf("arr[%d]: %d\n", i, arr[i]); // Array nochmal anzeigen

    return 0;
}

void ReadWriteIntoArray(int arraysize, int arrvar[][4]) // Funktion in die zwei Variablen hineingehen
                                                                                          // erstens die Arraygröße und zweitens
                                                                                          // der zweidimensionale Array selber
                                                                                          // diesmal wird die Größe der zweiten Dimension angegeben
{
   int i, j;

   for(i = 0; i < arraysize; i++)// for Schleife, kommt im nächsten Kapitel
   {
      for(j = 0; j < 4; j++)
      {
         printf("inside: arr[%d][%d]: %d\n", i, j, arrvar[i][j]);
         arrvar[i][j]++; // Arrayelement wird verändert
      }
   }
}

 

Probieren Sie die beiden Progrämmchen doch einfach mal aus und sehen sich den Output an.
Warum kann man den Array in der Funktion in folgender Zeile:

arrvar[i][j]++; // Arrayelement wird verändert

eigentlich ändern? Nun der Compiler organisiert die Variablenübergabe für Arrays by Reference, d.h es wird ein Pointer übergeben, der direkt auf den Speicherort des Arrays zeigt, wird später noch mal erklärt. Bei "normalen" Variablen übergibt der Compiler eine Kopie der Variable an die Funktion (by value), er legt einen neuen Speicherbereich an und kopiert dort den Inhalt der Variablen hinein. Bei Arrays tut er dies jedoch nicht, sondern übegint nur einen Pointer auf den Beginn des Speicherbereiches des Arrays. Das hat damit zu tun, das Arrays tendenziell sehr groß werden können und man so den Hauptspeicher sehr schnell verbraucht.

 

 

<= Previous











Die C/C++ Standard Referenz von Herb Schildt: