Wie viele Bytes belegt eine Variable?
Der Arbeitsspeicher eines Computers ist eine lange Reihe nummerierter Bytes. Jede Variable in C belegt einige davon, und die Nummer ihres ersten Bytes heißt Adresse.
Wer das versteht, weiß, warum ein int vier Bytes braucht und warum eine Struktur größer sein kann als die Summe ihrer Felder. Ein Fahrkartenautomat speichert jeden Preis in Cent als ganze Zahl, und genau das sehen wir uns an.
Am Ende dieser Lektion
Notiz
Ich kann sagen, wie groß eine Variable ist und wo sie im Speicher liegt.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Byte | eine Speicherzelle aus acht Bit | |
| Adresse | die Nummer eines Bytes im Speicher | |
| Datentyp | legt fest, wie viele Bytes eine Variable belegt | int |
| sizeof | ein Operator, der die Größe in Bytes liefert | sizeof(int) |
| Struktur | mehrere Felder unter einem Namen | struct |
| Polsterung | Füllbytes, die der Compiler zwischen Felder legt |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Jeder Datentyp belegt eine feste Zahl von Bytes
Der Datentyp einer Variablen sagt dem Compiler, wie viele Bytes sie belegt. Ein char passt in ein Byte, ein int braucht vier.
Ein Byte hält nur 256 Werte. Größere Zahlen verteilt der Rechner auf mehrere Bytes, und das kleinste Stück steht zuerst. Die Tabelle gilt für ein 64-Bit-Linux wie das Lab.
Beispiel: die Größen der Grundtypen
| Typ | Bytes | Wofür er sich eignet |
|---|---|---|
| char | 1 | ein Zeichen oder eine kleine Zahl |
| int | 4 | eine ganze Zahl, zum Beispiel ein Preis in Cent |
| long | 8 | eine sehr große ganze Zahl |
| double | 8 | eine Zahl mit Nachkommastellen |
| Zeiger | 8 | die Adresse einer anderen Variablen |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Eine Zahl als Bytes im Modellspeicher
# Modell: acht Bytes Speicher, alle auf 0
speicher = bytearray(8)
preis_cent = 1250
# Vier Bytes fuer eine Zahl, das kleinste Stueck steht zuerst
speicher[0:4] = preis_cent.to_bytes(4, "little")
print(list(speicher))
# Aendern Sie preis_cent auf 300 und fuehren Sie erneut aus.
Mit sizeof fragen Sie nach der Größe
Sie müssen Größen nicht auswendig kennen. Der Operator sizeof liefert sie in Bytes, und der Compiler setzt die Zahl für den Rechner ein, auf dem er läuft.
Das Programm unten gibt die Größen von vier Typen aus. Die Befehle darunter schreiben es in eine Datei, übersetzen es und starten es. Zuerst legen wir einen eigenen Ordner an.
Das Programm groessen.c
#include <stdio.h>
int main(void) {
printf("Bytes: char %zu, int %zu, long %zu, double %zu\n",
sizeof(char), sizeof(int), sizeof(long), sizeof(double));
return 0;
}
Einen Arbeitsordner anlegen
mkdir -p ~/csys && cd ~/csysHier 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 in eine Datei schreiben
printf '#include <stdio.h>\n\nint main(void) {\n printf("Bytes: char %%zu, int %%zu, long %%zu, double %%zu\\n",\n sizeof(char), sizeof(int), sizeof(long), sizeof(double));\n return 0;\n}\n' > groessen.cHier 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
gcc -o groessen groessen.cHier 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 starten
./groessenHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Eine Struktur hat Füllbytes zwischen den Feldern
Eine Struktur fasst mehrere Felder zusammen. Der Prozessor liest schnell, wenn ein Feld an einer Adresse beginnt, die ein Vielfaches seiner Größe ist.
Deshalb legt der Compiler Füllbytes (Polsterung) dazwischen. Am Ende rundet er die Gesamtgröße auf ein Vielfaches des größten Feldes. Die Reihenfolge der Felder ändert also die Größe.
Beispiel: dieselben Felder in zwei Reihenfolgen
| Struktur | Feld | Beginnt bei | Füllbytes danach |
|---|---|---|---|
| KarteAlt | zone (char) | 0 | 3 |
| KarteAlt | preis_cent (int) | 4 | 0 |
| KarteAlt | klasse (char) | 8 | 3 |
| KarteNeu | preis_cent (int) | 0 | 0 |
| KarteNeu | zone (char) | 4 | 0 |
| KarteNeu | klasse (char) | 5 | 2 |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Das zweite Programm in eine Datei schreiben
printf '#include <stdio.h>\n#include <stddef.h>\n\nstruct KarteAlt { char zone; int preis_cent; char klasse; };\nstruct KarteNeu { int preis_cent; char zone; char klasse; };\n\nint main(void) {\n printf("Alt %%zu, Neu %%zu, Versatz von preis_cent in Alt %%zu\\n",\n sizeof(struct KarteAlt), sizeof(struct KarteNeu), offsetof(struct KarteAlt, preis_cent));\n return 0;\n}\n' > karte.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das zweite Programm übersetzen
gcc -o karte karte.cHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Größen der Strukturen ausgeben
./karteHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein häufiger Fehler
Warnung
Viele glauben, die Größe einer Struktur sei die Summe ihrer Felder. Bei KarteAlt ergäbe das 6, sizeof liefert aber 12. Der Compiler fügt Füllbytes ein. Rechnen Sie die Größe nie selbst aus, sondern fragen Sie sizeof.