Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Arrays und Zeichenketten in C

Nach dieser Lektion: Ich kann erklären, warum ein Array Speicher ist und eine Zeichenkette Bytes mit einer Null am Ende.

Lektion, 60 Min.7 BefehleLab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Was sind Arrays und Strings in C?

Ein Array ist eine Reihe gleich großer Elemente direkt hintereinander im Speicher. Eine Zeichenkette (String) in C ist nichts anderes als ein char-Array, das mit dem Byte 0 endet.

Wer das weiß, versteht, warum ein zu langer Name in einem Formular das Nachbarfeld überschreiben kann. Dieser Fehler heißt Pufferüberlauf und gehört zu den ältesten Sicherheitslücken.

Am Ende dieser Lektion

Notiz

Ich kann erklären, warum ein Array Speicher ist und eine Zeichenkette Bytes mit einer Null am Ende.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Arrayeine Reihe gleich großer Elemente hintereinanderint tage[5]
Indexder Platz eines Elements, gezählt ab 0tage[0]
Zeichenketteein char-Array, das mit dem Byte 0 endet
Nullbytedas Byte mit dem Wert 0 am Ende\0
Pufferein Speicherbereich fester Größe
PufferüberlaufSchreiben über das Ende eines Puffers hinaus

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein Array ist Speicher ohne Lücken

Die Elemente eines Arrays liegen ohne Lücken hintereinander. Das Element mit dem Index i liegt bei Start + i * Größe des Elements.

Deshalb gelingt der Zugriff über den Index so schnell: Der Rechner rechnet nur eine Adresse aus. Das erste Element hat den Index 0, weil es bei der Startadresse selbst liegt.

Beispiel: das Array tage mit fünf ints

IndexVersatz zum Start in BytesWert
0031
1428
2831
31230
41631

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

In den Arbeitsordner wechseln

Befehl
mkdir -p ~/csys && cd ~/csys

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Ein Programm mit einem Array schreiben

Befehl
printf '#include <stdio.h>\n\nint main(void) {\n    int tage[5] = {31, 28, 31, 30, 31};\n    printf("Array: %%zu Bytes, %%zu Elemente\\n", sizeof(tage), sizeof(tage) / sizeof(tage[0]));\n    return 0;\n}\n' > tage.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Das Programm übersetzen

Befehl
gcc -o tage tage.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Größe und Elementzahl ausgeben

Befehl
./tage

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Eine Zeichenkette endet mit dem Byte 0

C kennt keinen eigenen Typ für Text. Eine Zeichenkette ist ein char-Array, dessen letztes Byte der Wert 0 ist, das Nullbyte. Nur so weiß strlen, wo der Text endet.

Darum braucht der Text "Hallo" sechs Bytes, obwohl er fünf Buchstaben hat. Ein Umlaut belegt im UTF-8-Text zwei Bytes, strlen zählt also Bytes und keine Zeichen.

Eine Zeichenkette im Modellspeicher

Code: python
# Modell: die Zeichenkette "Moin" als Bytes, danach das Nullbyte
speicher = bytearray(8)
text = b"Moin"
for i in range(len(text)):
    speicher[i] = text[i]
speicher[len(text)] = 0        # das Nullbyte beendet die Zeichenkette
print(list(speicher[0:6]))
# Ersetzen Sie "Moin" durch b"Hallo" und fuehren Sie erneut aus.

Ein Programm mit Zeichenketten schreiben

Befehl
printf '#include <stdio.h>\n#include <string.h>\n\nint main(void) {\n    char gruss[] = "Hallo";\n    printf("Text: strlen %%zu, sizeof %%zu, letztes Byte %%d\\n", strlen(gruss), sizeof(gruss), gruss[5]);\n    char kaese[] = "Käse";\n    printf("Käse: %%zu Bytes\\n", strlen(kaese));\n    return 0;\n}\n' > text.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Das Programm übersetzen

Befehl
gcc -o text text.c

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Längen und Größen ausgeben

Befehl
./text

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Ein Pufferüberlauf überschreibt den Nachbarn

Ein Puffer hat eine feste Größe, und C prüft beim Schreiben nicht nach. Kopieren Sie einen zu langen Text hinein, landen die übrigen Bytes im Speicher dahinter, vielleicht in einer anderen Variablen.

Echtes C liefert dann ein undefiniertes Ergebnis, deshalb führen wir das nie aus. Das Modell unten zeigt deterministisch, was dabei geschehen kann.

Ein Überlauf im Modellspeicher

Code: python
# Modell: Adressen 0 bis 3 sind der Puffer, 4 bis 7 gehoeren der Variable recht
speicher = bytearray(12)
speicher[4] = 1                # recht = 1, ein Gast darf nur lesen
name = b"Eva Maier"            # neun Bytes, der Puffer hat nur vier
for i in range(len(name)):     # kein Test gegen die Puffergroesse
    speicher[i] = name[i]
print("Puffer:", list(speicher[0:4]))
print("recht:", speicher[4])

Ein häufiger Fehler

Warnung

Viele glauben, ein Puffer für einen Text mit vier Zeichen brauche vier Bytes. Das Nullbyte kommt dazu, es sind fünf. Bei vier Bytes wäre das Nullbyte schon außerhalb des Puffers. Prüfen Sie immer, ob Länge plus eins in den Puffer passt.

Über dieses Lab und seinen Quellcode: Lab für Compilerbau und Rechnerarchitektur: gcc, flex, bison und RISC-V in einer VM

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.