B.8    Antworten und Lösungen zu Kapitel 9

  1. Arrays sind Datenstrukturen, in denen sich mehrere Werte eines bestimmten Typs speichern und bearbeiten lassen. Der Zugriff auf die Daten erfolgt mithilfe des Indizierungsoperators [] über einen Index. Ein Array kann eine oder auch mehrere Dimensionen haben und so sowohl als eine Folge von Werten (z. B. in einem String) als auch z. B. als Tabelle abgelegt werden.

  2. Zunächst einmal sind Strings nichts anderes als Arrays vom Datentyp char (bzw. wchar_t). Allerdings sind die char-Arrays die einzige Möglichkeit, um eine Folge von Zeichen, also einen String (auch Zeichenkette genannt) zu speichern. Einen eigenen Datentyp für Strings gibt es in C nicht. Wichtig bei einem char-Array ist: Damit Sie dieses auch wirklich als echten String verwenden können, müssen Sie es mit einem Null-Zeichen oder auch Stringende-Zeichen '\0' abschließen. Demnach muss ein String immer um ein Zeichen länger als die Anzahl der relevanten Zeichen sein, damit das Stringende-Zeichen am Ende auch noch Platz hat.

  3. Die größte Gefahr geht davon aus, dass Sie mehr Daten in ein Array oder einen String schreiben, als Speicherplatz dafür vorhanden ist. Wenn Sie beispielsweise ein Array mit 10 Elementen angelegt haben, aber nun 11 Elemente in das Array schreiben, weil Sie den Indexbereich versehentlich überschreiten, dann haben Sie einen Pufferüberlauf provoziert. Häufig beendet sich das Programm dann mit einem Speicherzugriffsfehler. Ein solcher Fehler kann aber nur schwer gefunden werden und eventuell auch zu falschen Rechenergebnissen führen. In der Netzwerkprogrammierung kann dies ganz böse Folgen haben, weil sich solche Fehler für Angriffe ausnutzen lassen, mit denen z. B. Viren in den jeweiligen Rechner eingeschleust werden können. Ein populäres Beispiel aus den letzten Jahren ist ein Pufferüberlauf in der Ladebibliothek für JPEG-Bilder auf verschiedenen Browsern. Hierdurch ließen sich verschiedene Trojaner einschleusen, die Login-Daten und Passwörter der infizierten Rechner ausspionieren konnten.

  4. Ein beliebter Anfängerfehler ist, zu vergessen, dass das erste Element eines Arrays bzw. Strings immer mit der Indexnummer 0 beginnt und das letzte Element immer die Indexnummer N-1 hat. (N ist die angegebene Array-Größe.) Daher wird hier oft ein Überlauf erzeugt, weil auf die Indexnummer N anstatt auf N-1 zugegriffen wird. Bei Strings wird häufig vergessen, dass noch Platz für das Stringende-Zeichen vorhanden sein muss.

  5. In der for-Schleife in Zeile (06) wurden gleich zwei Fehler gemacht. Da i mit MAX initialisiert wurde, wurde dem Array mit dem Index 10 ein Wert übergeben. Somit wäre dies ein Array-Überlauf, weil die Indexnummern nur von 0 bis 9 gehen. Des Weiteren würde durch die Überprüfung, ob i größer als 0 ist, das Array-Element mit dem Index 0 nicht initialisiert. In der for-Schleife in Zeile (06) muss daher MAX-1 an i übergeben werden, und die Schleifenbedingung sollte auf größer-gleich 0 geprüft werden:

    06    for(int i = MAX-1; I >= 0; i--) { 
  6. Dass das char-Array v in Zeile (05) nicht mit \0 abgeschlossen wird, ist nicht der Fehler. Der Fehler wurde erst in Zeile (10) des Programms gemacht: Dort wird das char-Array als String behandelt. Das sollten Sie vermeiden, wenn kein Stringende-Zeichen vorhanden ist. Sie haben folgende zwei Möglichkeiten, damit v als korrekter String angesehen werden kann:

    char v[6] = { 'A', 'E', 'I', 'O', 'U', '\0' }; 
    char v[6] = { "AEIOU" };
  7. Hier sehen Sie eine mögliche Musterlösung der Aufgabe:

    00  // kap009/loesung001.c 
    01 #include <stdio.h>
    02 #include <stdlib.h>
    03 #include <string.h>

    04 int main(void) {
    05 int iarr[] = { 2, 4, 6, 4, 2, 4, 5, 6, 7 };
    06 double darr[] = { 3.3, 4.4, 2.3, 5.8, 7.7 };
    07 char str[] = { "Hallo Welt"};

    08 printf("iarr: %zu Bytes\n", sizeof(iarr));
    09 printf("iarr: %zu Elemente\n", sizeof(iarr)/sizeof(int));
    10 printf("darr: %zu Bytes\n", sizeof(darr));
    11 printf("darr: %zu Elemente\n", sizeof(darr)/sizeof(double));
    12 printf("str : %zu Bytes\n", sizeof(str));
    13 printf("str : %zu Elemente (sizeof)\n", sizeof(str)/
    sizeof(char));
    14 printf("str : %zu Elemente (strlen)\n", strlen(str)+1);
    15 return EXIT_SUCCESS;
    16 }

    Das Programm gibt bei der Ausführung Folgendes aus:

    iarr: 36 Bytes 
    iarr: 9 Elemente
    darr: 40 Bytes
    darr: 5 Elemente
    str : 11 Bytes
    str : 11 Elemente (sizeof)
    str : 11 Elemente (strlen)
  8. Eine Musterlösung:

  9. Eine Musterlösung: