MINT lernen

Übungen: Speicher

Jede Variable hat eine Hausnummer im Speicher — kannst du sie ausrechnen, bevor das Programm sie verrät?

Dein Fortschritt:
0 / 0 Aufgaben
1

Übungsaufgaben

Zehn Übungen zum Klicken, Zuordnen, Nachverfolgen und Knobeln — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du nicht weiterkommst, helfen dir die gestuften Tipps.

A1
Schreibweisen rund um den Speicher
AFB I

Ordne jeder Schreibweise ihre Bedeutung zu. Die Byte-Angaben gelten für einen typischen PC.

Ansatz: Das Zeichen & vor einem Variablennamen fragt: „Wo liegst du?“
Weiter: Hexadezimal: Die zweite Stelle von rechts zählt Sechzehner.
A2
Wo endet die Variable?
AFB I

Eine int-Variable belegt ab Adresse 0x2FFC typischerweise 4 Byte. Gib die Adresse ihres letzten Bytes an.

Trag die Adresse in Hex-Schreibweise ein — Enter prüft direkt.
Die vier Bytes liegen bei 0x2FFC, 0x2FFD, 0x2FFE und 0x2FFF — das letzte Byte ist 0x2FFC + 3. Typischer Fehler: 0x3000 (= 0x2FFC + 4). Das ist schon das erste Byte hinter der Variablen. In Hex folgen nach 9 die Ziffern A bis F: C, D, E, F.
Ansatz: Zähle die vier Bytes einzeln ab, beginnend bei 0x2FFC.
Weiter: Nach C kommen in Hex D, E, F.
A3
Stimmt's? — Bytes und Adressen
AFB I

Fünf Behauptungen über den Arbeitsspeicher. Nenne jeweils, ob sie stimmt.

Fünf Aussagen nacheinander. Eine falsche Einschätzung reicht — dann startest du die Serie mit „Neue Runde“ neu.
Aussage 1 von 5

Die letzte Aussage ist der Klassiker: Ohne & bekommt scanf nur den (zufälligen) Wert der Variablen und schreibt an eine unsinnige Stelle — meist stürzt das Programm ab. Bei printf ist es umgekehrt: Dort genügt der Wert.
Ansatz: Unterscheide immer zwischen dem Wert einer Variablen und ihrer Adresse.
Weiter: Hexadezimalzahlen erkennst du am Präfix 0x.
A4
Speicherplan des Fahrradcomputers
AFB II
C · Variablen des Fahrradcomputers
double t;   // Fahrzeit
int m;      // Meter
char k;     // Kennbuchstabe
int z;      // Zähler

Nimm vereinfacht an, dass die Variablen lückenlos in dieser Reihenfolge ab Adresse 0x2000 liegen und die typischen Größen haben. Bestimme für jede Variable Größe, erste und letzte Adresse.

Füll alle Felder aus und prüfe dann. Enter in einem Feld prüft ebenfalls.
VariableByteerste Adresseletzte Adresse
double t;
int m;
char k;
int z;
Letzte Adresse = erste Adresse + Größe − 1; die nächste Variable beginnt eins dahinter. Die Stolperstellen sind die Hex-Übergänge: 0x2008 + 3 = 0x200B (nicht 0x2011!) und 0x200D + 3 = 0x2010. Beim char sind erste und letzte Adresse gleich. Echte Compiler lassen oft Lücken, damit int und double auf „glatten“ Adressen liegen — deshalb „vereinfacht“.
Ansatz: Beginne mit t: 8 Byte ab 0x2000 enden bei 0x2007.
Weiter: Nach 0x2009 kommt in Hex 0x200A, dann 0x200B …
A5
Wert, Adresse oder Größe?
AFB II
C · Deklarationen
int x = 7;
double preis = 1.5;
char zeichen = 'M';

Ordne jeden Ausdruck danach ein, was er liefert.

Ziehe jede Karte in den passenden Korb — oder wähle sie mit Enter aus und drücke dann die Ziffer des Korbs (0 legt sie zurück).
1einen gespeicherten Wert
2eine Adresse
3eine Größe in Byte
Achtung bei x + 1: Das ist schlicht 8 — ein Wert, keine Adresse. Und &zeichen ist eine Adresse wie jede andere, obwohl dort nur 1 Byte liegt. sizeof fragt nie nach dem Inhalt: sizeof(x) ist 4, egal ob x gerade 7 oder 7000 ist.
Ansatz: Ein & davor macht aus jeder Variablen eine Adresse.
Weiter: sizeof beantwortet „wie viel Platz?“, nicht „was steht drin?“.
A6
Einlesen und Adresse zeigen
AFB II
So soll es aussehen (Adresse ändert sich bei jedem Start)
Alter: 14
Du bist 14 Jahre alt.
alter liegt bei 0x7ffd3a1c

Ergänze die Lücken so, dass das Programm wie gezeigt arbeitet.

Wähle in jedem Menü den passenden Eintrag und prüfe dann alle auf einmal.
C · Ausschnitt
int alter;
printf("Alter: ");
scanf("", );
printf("Du bist %d Jahre alt.\n", );
printf("alter liegt bei \n", );
Die Regel in einem Satz: scanf braucht die Adresse (wohin schreiben?), printf mit %d den Wert. Typischer Fehler: auch in der ersten Ausgabe &alter schreiben — dann erscheint eine riesige Zahl statt 14, und gcc warnt. Für Adressen ist %p die richtige Formatangabe.
Ansatz: Frage bei jedem Aufruf: Soll die Funktion etwas hineinschreiben oder nur anzeigen?
Weiter: Eine Adresse ist keine normale Ganzzahl — dafür gibt es eine eigene Formatangabe.
A7
Ein Speicherbereich wird aufgeteilt
AFB II

Die Schul-Wetterstation hat für Messwerte den Speicherbereich von 0x2A00 bis einschließlich 0x2AFF reserviert. Berechne Schritt für Schritt (typische Größen).

Arbeite die Kette Schritt für Schritt ab: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
  1. Wie viele Byte umfasst der Bereich? Byte
  2. Wie viele int-Werte passen hinein?
  3. Wie viele double-Werte passen hinein?
  4. Bei welcher Adresse beginnt der letzte int-Wert?
0x2AFF − 0x2A00 = 0xFF = 255 — aber beide Grenzen gehören dazu, also 256 Byte. Genau hier liegt der häufigste Fehler (255). 256 : 4 = 64 und 256 : 8 = 32. Der letzte int belegt die letzten 4 Byte 0x2AFC bis 0x2AFF.
Ansatz: Rechne die Differenz der Adressen in dezimal um: 0xFF = 15 · 16 + 15.
Weiter: Zähle beide Randadressen mit — wie bei „von Seite 1 bis Seite 10“ sind es 10 Seiten.
A8
Fehlersuche: Punktestand
AFB III

Das Programm für den Punktestand im Spiel soll Punkte einlesen, sie mit Bonus ausgeben und zeigen, wo die Variable im Speicher liegt. Untersuche den Code — drei Zeilen sind fehlerhaft.

In diesem Code stecken Fehler. Klicke genau die fehlerhaften Zeilen an — die richtigen musst du stehen lassen.
Die drei Fehler sind Spiegelbilder derselben Frage „Wert oder Adresse?“. gcc meldet sie mit -Wall alle als Warnung — und übersetzt trotzdem. Korrekt ist dagegen Zeile 8: Der cast (int) passt das Ergebnis von sizeof an %d an. Zeile 7 ist das richtige Muster für die Adressausgabe.
Ansatz: Markiere dir für jede Zeile: Wird hier ein Wert oder eine Adresse gebraucht — und was steht tatsächlich da?
Weiter: Die Paare lauten: scanf ↔ Adresse, %d ↔ Wert, %p ↔ Adresse.
A9
Summieren bis zur Null
AFB III Mix

Mit der do … while-Schleife aus 2.1.3 und scanf soll ein Programm Zahlen einlesen, bis 0 eingegeben wird, und dann die Summe ausgeben. Für die Eingaben 4, 7, 0 erscheint Summe: 11. Implementiere das Programm, indem du die Zeilen ordnest.

Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1int zahl, summe = 0;
2do {
3 printf("Zahl (0 = Ende): ");
4 scanf("%d", &zahl);
5 summe += zahl;
6} while (zahl != 0);
7printf("Summe: %d\n", summe);
Am häufigsten verrutscht summe += zahl; vor das scanf: Dann wird im ersten Durchlauf ein noch unbestimmter Wert addiert. Die abschließende 0 wird mitaddiert — das schadet nicht. Genau dafür passt do … while: Die Bedingung kann erst geprüft werden, nachdem einmal eingelesen wurde.
Ansatz: Eine Zahl kann erst addiert werden, nachdem sie eingelesen wurde — und eingelesen erst, nachdem die Aufforderung erschienen ist.
Weiter: Die Bedingung zahl != 0 steht bei do … while hinter dem Rumpf.
A10
Wie groß ist der Ausdruck?
AFB III Trick
C · Deklarationen
double x = 1.5;
char k = 100;

Lege für jeden Ausdruck fest, welchen Wert er auf einem typischen PC hat.

Wähle für jede Zeile eine Stufe: 1 = 1 Byte, 2 = 4 Byte, 3 = 8 Byte, 4 = 12 Byte, 5 = 16 Byte. Mit der Tastatur: Tab zur Zeile, ←/→ zwischen den Stufen, Enter setzt.
1 = 1 Byte5 = 16 Byte
sizeof(int)
sizeof(2.5)
sizeof(int) + sizeof(double)
sizeof(10 / 4)
sizeof(10 / 4.0)
sizeof(x) * 2
sizeof(k)
sizeof misst den Typ eines Ausdrucks, nicht seinen Wert. 10 / 4 ist ein int (Wert 2) → 4 Byte; 10 / 4.0 ist ein double → 8 Byte; die Zahl 2.5 ist ebenfalls ein double. Die Falle: sizeof(k) ist 1, obwohl in k die Zahl 100 steht — ein char belegt immer 1 Byte.
Ansatz: Bestimme für jeden Ausdruck zuerst seinen Typ: int, double oder char?
Weiter: Eine Kommazahl im Quelltext wie 2.5 hat den Typ double.