Homepage  • Privacy Policy & Imprint

Integer-Typen in Delphi und FreePascal

Was ist ein Integer?

Wenn man in einem Programm mit ganzen Zahlen arbei­ten möchte, also Zahlen ohne Nachkomma­stellen wie 5, -12 oder 1000, dann ver­wendet man einen Integer-Typ (vom lateini­schen *integer* = „ganz“). Integer-Typen sind die am häufigs­ten ge­nutzten Daten­typen in der Programmie­rung über­haupt, denn viele alltäg­liche Dinge lassen sich damit ab­bilden: Zähler, Indizes, Ergebnisse von Berech­nungen, Alter, Anzahl von Elemen­ten usw.

In Pascal deklariert man eine Variable so:

var
  MeineZahl: Integer;

Danach kann man ihr einen Wert zuweisen und mit ihr rechnen:

MeineZahl := 42;
MeineZahl := MeineZahl + 8;  // MeineZahl ist jetzt 50

2. Warum gibt es mehrere Integer-Typen?

Eine naheliegende Frage ist: Warum reicht nicht ein einziger Integer-Typ für alle Zwecke? Die Antwort liegt im Speicher. Jeder Datentyp belegt eine be­stimmte Anzahl an Bits im Arbeits­speicher, und die Anzahl der Bits bestimmt, wie große (oder wie kleine) Zahlen man darin speichern kann.

Ein Bit kann nur zwei Zustände an­nehmen: 0 oder 1. Mit 8 Bit (= 1 Byte) kann man 2⁸ = 256 ver­schiedene Werte dar­stellen. Mit 16 Bit sind es 2¹⁶ = 65.536 Werte, mit 32 Bit schon 2³² = über 4 Milliarden, und mit 64 Bit ent­sprechend 2⁶⁴ - eine astronomisch große Zahl.

Außerdem gibt es für jeden Größenbereich zwei Varianten:

- Vorzeichenbehaftet (signed): Die Zahl kann negativ oder positiv sein. Die Hälfte der mög­li­chen Werte wird für negative Zahlen ge­nutzt.

- Vorzeichenlos (unsigned): Die Zahl ist immer ≥ 0. Dafür ist der positive Werte­bereich doppelt so groß.

Diese Überlegungen führen zu einer ganzen Familie von Integer-Typen, die Pascal bereit­stellt.


3. Der Typ `Integer` - Der meistgenutzte Typ

Grundlagen

In Delphi und FreePascal ist `Integer` der Standard-Integer-Typ und der, den man im All­tag am häufigs­ten sieht. Er ist vorzeichen­behaftet und hat einen Werte­bereich von:

> -2.147.483.648 bis 2.147.483.647

Das sind gut ±2 Milliarden. Für die allermeisten Alltags­aufgaben - Zähler, Indizes, Berechnun­gen - ist dieser Bereich mehr als aus­reichend.

Wie groß ist `Integer` genau?

Hier gibt es einen wichtigen Unterschied zwi­schen Delphi und FreePascal:

- In Delphi ist `Integer` seit Delphi 2 fest als 32-Bit-Typ definiert und bleibt das auch auf 64-Bit-Systemen. Delphi hat sich bewusst für diese Stabili­tät ent­schieden.

- In FreePascal ist `Integer` ebenfalls standard­mäßig ein 32-Bit-Typ (ein Alias für `LongInt`), allerdings kann das in be­stimmten Compiler-Modi oder auf exo­ti­schen Plattformen abweichen.

Für die täg­liche Arbeit unter Windows kann man davon aus­gehen: `Integer` = 32 Bit = 4 Byte.

Einfaches Beispiel

program IntegerBeispiel;

var
  Alter: Integer;
  Punkte: Integer;
  Summe: Integer;

begin
  Alter := 25;
  Punkte := 1500;
  Summe := Alter + Punkte;

  WriteLn('Alter: ', Alter);
  WriteLn('Punkte: ', Punkte);
  WriteLn('Summe: ', Summe);
end.

4. Die festen Integer-Typen im Überblick

Diese Typen haben eine garantierte, plattform­unabhängige Größe - egal ob man für 32-Bit oder 64-Bit kompiliert, sie ver­halten sich immer gleich. Das macht sie beson­ders zuver­lässig, wenn man genaue Kontrolle über den Speicher braucht.

4.1 Vorzeichenbehaftete Typen (Signed)

`ShortInt` - 8 Bit

var s: ShortInt;
- Größe: 1 Byte (8 Bit) - Wertebereich: -128 bis 127 - Verwendung: Selten im Alltag. Sinnvoll wenn sehr viele kleine Zahlen­werte ge­speichert werden sollen und Speicher knapp ist, z.B. in großen Arrays.
var
  Temperatur: ShortInt;
begin
  Temperatur := -15;  // Passt problemlos
  Temperatur := 200;  // FEHLER! 200 > 127, Überlauf!
end;

`SmallInt` - 16 Bit

var s: SmallInt;

- Größe: 2 Byte (16 Bit)

- Wertebereich: -32.768 bis 32.767

- Verwendung: Für Werte, die etwas größer als ein Byte sein müssen, aber nie die 32.767 über­schrei­ten. Beispiels­weise Koordina­ten in kleinen Grafik­programmen.

var
  X, Y: SmallInt;
begin
  X := 1920;   // Bildschirmkoordinate - passt noch
  Y := 1080;   // Passt auch
  X := 40000;  // FEHLER! Überlauf!
end;

`LongInt` - 32 Bit

var l: LongInt;

- Größe: 4 Byte (32 Bit)

- Wertebereich: -2.147.483.648 bis 2.147.483.647

- Verwendung: Iden­tisch mit `Integer` (in Delphi und FreePascal ist `Integer` ein Alias dafür). Wenn man explizit 32 Bit garantie­ren möchte, nimmt man `LongInt`.

`Int64` - 64 Bit

var i: Int64;

- Größe: 8 Byte (64 Bit)

- Wertebereich: -9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807

- Verwendung: Wenn 32 Bit nicht reichen. Typische Einsatz­gebiete: Datei­größen, Zeit­stempel (Unix-Zeit in Milli­sekunden), sehr große Zähler oder wissen­schaft­liche Berech­nungen.

var
  Dateigroesse: Int64;
begin
  Dateigroesse := 10 * 1024 * 1024 * 1024;  // 10 Gigabyte in Bytes
  WriteLn('Dateigröße: ', Dateigroesse, ' Bytes');
end;

Hinweis: Bei `Int64`-Berechnungen muss man auf­passen, dass Zwischen­ergebnisse nicht über­laufen. Der Aus­druck `10 * 1024 * 1024 * 1024` wird vom Compiler standard­mäßig als 32-Bit-Berech­nung durch­geführt, was einen Über­lauf er­zeugen kann. Besser: mindes­tens einen Operanden expli­zit als `Int64` schreiben: `Int64(10) * 1024 * 1024 * 1024`.


4.2 Vorzeichenlose Typen (Unsigned)

Vorzeichenlose Typen können keine negativen Zahlen speichern. Dafür ist ihr positi­ver Werte­bereich doppelt so groß wie der des ent­sprechen­den vorzeichen­behafte­ten Typs.

`Byte` - 8 Bit, unsigned

var b: Byte;

- Größe: 1 Byte (8 Bit)

- Wertebereich: 0 bis 255

- Verwendung: Sehr häufig! Einzelne Bytes in Binär­daten, RGB-Farb­werte (0-255), kleine Flags.

var
  Rot, Gruen, Blau: Byte;
begin
  Rot   := 255;  // Maximale Intensität
  Gruen := 128;
  Blau  := 0;
  // Rot := -1;  // FEHLER! Unsigned kann nicht negativ sein
end;

`Word` - 16 Bit, unsigned

var w: Word;

- Größe: 2 Byte (16 Bit)

- Wertebereich: 0 bis 65.535

- Verwendung: Portnummern im Netzwerk (0-65535), Zeichencodes, ältere Datei­formate.

var
  Port: Word;
begin
  Port := 8080;   // Typischer HTTP-Alternativport
  Port := 443;    // HTTPS
end;

`LongWord` - 32 Bit, unsigned

var lw: LongWord;

- Größe: 4 Byte (32 Bit)

- Wertebereich: 0 bis 4.294.967.295

- Verwendung: IPv4-Adressen (intern als 32-Bit-Zahl), Hashwerte, Windows-API-Typen (`DWORD` ent­spricht diesem Typ).

- Aliase: In Delphi und FreePascal auch als `Cardinal` bekannt (ebenfalls 32 Bit, unsigned).

var
  IPAdresse: LongWord;
begin
  // 192.168.1.1 als 32-Bit-Zahl (Big-Endian)
  IPAdresse := (192 shl 24) or (168 shl 16) or (1 shl 8) or 1;
end;

`QWord` - 64 Bit, unsigned

var q: QWord;

- Größe: 8 Byte (64 Bit)

- Wertebereich: 0 bis 18.446.744.073.709.551.615

- Verwendung: Sehr große vorzeichenlose Werte, Bitmasks in 64-Bit-Systemen, krypto­grafische Be­rech­nungen.


5. Übersichtstabelle aller festen Typen

| Typ | Vorzeichen | Bits | Bytes | Minimum | Maximum |

|---|---|---|---|---|---|

| `ShortInt` | ja | 8 | 1 | -128 | 127 |

| `Byte` | nein | 8 | 1 | 0 | 255 |

| `SmallInt` | ja | 16 | 2 | -32.768 | 32.767 |

| `Word` | nein | 16 | 2 | 0 | 65.535 |

| `LongInt` | ja | 32 | 4 | -2.147.483.648 | 2.147.483.647 |

| `LongWord` | nein | 32 | 4 | 0 | 4.294.967.295 |

| `Int64` | ja | 64 | 8 | -9,2 × 10¹⁸ | 9,2 × 10¹⁸ |

| `QWord` | nein | 64 | 8 | 0 | 1,8 × 10¹⁹ |


6. Aliase und Kurzformen

Pascal kennt einige Aliase, also alternative Namen für den­selben Typ. Es ist gut, sie zu kennen, damit man beim Lesen von fremdem Code nicht ver­wirrt wird:

| Alias | Entspricht | Bits |

|---|---|---|

| `Integer` | `LongInt` | 32 |

| `Cardinal` | `LongWord` | 32 |

| `DWord` | `LongWord` | 32 |

| `UInt64` | `QWord` | 64 |


7. Der Überlauf - Eine häufige Fehlerquelle

Einer der häufigsten Anfängerfehler ist der Integer-Überlauf (*overflow*). Er passiert, wenn das Ergeb­nis einer Berech­nung den Werte­bereich des Typs über­schreitet. Der Wert „rollt“ dann um - ähn­lich wie ein Kilometerzähler, der nach 99.999 wieder bei 0 beginnt.

var
  b: Byte;
begin
  b := 255;
  b := b + 1;   // Überlauf! b ist jetzt 0, nicht 256
  WriteLn(b);   // Gibt 0 aus
end;

Standardmäßig prüft FreePascal nicht zur Laufzeit auf Über­läufe. Man kann die Prüfung aber aktivieren:

{$R+}  // Range-Checking einschalten
{$Q+}  // Overflow-Checking einschalten

Mit diesen Compiler-Direktiven bricht das Programm bei einem Über­lauf mit einer Fehler­meldung ab, anstatt still­schweigend falsche Ergeb­nisse zu liefern. Das ist beson­ders beim Ent­wickeln und Testen sehr hilfreich.


8. Typumwandlung zwischen Integer-Typen

Manchmal muss man einen Wert von einem Typ in einen anderen um­wandeln. Dafür gibt es ver­schiede­ne Möglich­keiten:

Implizite Umwandlung (automatisch)

Pascal erlaubt automa­tische Umwand­lung von einem kleineren in einen größeren Typ, wenn das verlust­frei mög­lich ist:

var
  b: Byte;
  i: Integer;
begin
  b := 100;
  i := b;  // Kein Problem: Byte passt immer in Integer
end;

Explizite Umwand­lung (Typcast)

Umgekehrt - vom größeren in den kleine­ren Typ - muss man explizit um­wandeln. Pascal warnt hier, weil Daten­verlust mög­lich ist:

var
  i: Integer;
  b: Byte;
begin
  i := 200;
  b := Byte(i);    // Expliziter Cast: funktioniert hier, weil 200 in Byte passt
  i := 300;
  b := Byte(i);    // Überlauf! 300 mod 256 = 44 - b ist 44
end;

Mit Hilfsfunktionen prüfen

Es ist gute Praxis, vor einer Umwand­lung zu prüfen, ob der Wert in den Ziel­typ passt:

var
  i: Integer;
  b: Byte;
begin
  i := 200;
  if (i >= 0) and (i <= 255) then
    b := Byte(i)
  else
    WriteLn('Wert passt nicht in ein Byte!');
end;

9. Plattformabhängige Typen

Bisher haben alle besprochenen Typen eine feste Größe - egal auf welcher Platt­form. Es gibt aber auch Typen, deren Größe sich an die Ziel­plattform an­passt. Das klingt zunächst unsicher, hat aber einen wichtigen Vorteil: Der Typ ist immer genau so groß wie die native Wortbreite des Prozessors, was oft die effizienteste Wahl ist.

`NativeInt` und `NativeUInt`

Diese Typen sind genau so groß wie ein Zeiger auf der jeweiligen Plattform:

- Auf einem 32-Bit-System: 32 Bit (4 Byte)

- Auf einem 64-Bit-System: 64 Bit (8 Byte)

var
  n: NativeInt;
begin
  n := SizeOf(Pointer);  // 4 auf 32-Bit, 8 auf 64-Bit
  WriteLn('Zeigergröße: ', n, ' Bytes');
end;

`NativeInt` ist vorzeichenbehaftet, `NativeUInt` vorzeichenlos. Diese Typen nutzt man vor allem dann, wenn man Zeiger­arithmetik betreibt oder direkt mit Speicher­adressen arbeitet.

`SizeInt` und `SizeUInt`

`SizeInt` ist ein FreePascal-spezifischer Typ. Er ist ebenfalls plattform­abhängig und hat die­selbe Größe wie `NativeInt`. Der Name deutet auf seinen Haupt­verwendungs­zweck hin: Er ist der Typ, den FreePascal intern für Größenangaben und Indizes verwendet.

- In der FreePascal-Standardbibliothek ist `SizeInt` der Rückgabetyp von `SizeOf()` und `Length()`.

- `SizeUInt` ist die vorzeichenlose Variante, ent­sprechend dem C-Typ `size_t`.

var
  Laenge: SizeInt;
  MeinArray: array of Integer;
begin
  SetLength(MeinArray, 100);
  Laenge := Length(MeinArray);  // Length gibt SizeInt zurück
  WriteLn('Länge: ', Laenge);
end;

Wann sollte man `SizeInt` verwenden? Immer dann, wenn man mit Längen, Größen oder Indizes von Daten­strukturen arbei­tet, die theore­tisch auf 64-Bit-Systemen sehr groß werden könn­ten. Ein `Integer` (32 Bit) kann maximal ~2 Milliarden als Index darstellen - auf einem 64-Bit-System mit `SizeInt` sind deut­lich größere Strukturen möglich.

`PtrInt` und `PtrUInt`

Diese Typen sind ebenfalls plattform­abhängig und in FreePascal speziell für das Speichern von Zeiger­werten in Integer-Variablen gedacht. Sie sind genauso groß wie ein Zeiger und können deshalb verlustfrei eine Speicheradresse aufnehmen.

var
  Adresse: PtrUInt;
  Zahl: Integer;
begin
  Zahl := 42;
  Adresse := PtrUInt(@Zahl);  // Adresse der Variable als Zahl
  WriteLn('Adresse: ', Adresse);
end;

Das ist vor allem in der Systemprogrammie­rung relevant, z.B. wenn man mit der Windows-API oder mit dynamisch alloziier­tem Speicher arbeitet.

Übersicht der plattformabhängigen Typen

| Typ | Vorzeichen | 32-Bit-System | 64-Bit-System | Verwendung |

|---|---|---|---|---|

| `NativeInt` | ja | 32 Bit | 64 Bit | Zeigerarithmetik |

| `NativeUInt` | nein | 32 Bit | 64 Bit | Zeigerarithmetik |

| `SizeInt` | ja | 32 Bit | 64 Bit | Längen, Indizes |

| `SizeUInt` | nein | 32 Bit | 64 Bit | Längen (unsigned) |

| `PtrInt` | ja | 32 Bit | 64 Bit | Zeiger als Integer |

| `PtrUInt` | nein | 32 Bit | 64 Bit | Zeiger als Integer |


10. Welchen Typ soll man wann verwenden?

Als Faustregel für den Alltag:

- Integer ist die erste Wahl für normale ganz­zahlige Variablen. Er ist leicht zu lesen, gut ver­standen und reicht für die meisten Aufgaben.

- Byte nimmt man für einzelne Datenbytes, Farb­werte oder wenn man sich auf den Bereich 0-255 verlassen möchte.

- LongInt / LongWord verwendet man, wenn man die 32-Bit-Größe explizit und plattform­unabhängig garantie­ren möchte - z.B. beim Lesen und Schreiben von Binär­dateien mit festem Format.

- Int64 greift man, wenn 32 Bit nicht reichen: Datei­größen > 2 GB, große Zähler, Zeitstempel.

- SizeInt ist die richtige Wahl für Längen und Indizes, wenn Code sowohl auf 32-Bit- als auch auf 64-Bit-Systemen korrekt und effizient laufen soll.

- NativeInt / PtrInt gehören in die System­programmierung, wenn man direkt mit Zeigern und Speicher­adressen hantiert.

Mit diesem Werkzeugkasten ist man für prak­tisch alle Aufgaben ge­rüstet, die in der Pascal-Programmie­rung mit ganzen Zahlen auf­tauchen.


Back  •  Scroll to Top  • Homepage  • String types