Menu

Datentypen in C: int, float, char, double und mehr

Jede C-Variable hat einen Typ, der ihre Größe und ihren möglichen Inhalt festlegt. Hier sind alle Grundtypen, ihre tatsächlichen Größen, vorzeichenbehaftet gegen vorzeichenlos, sizeof, limits.h und was bei einem Überlauf passiert.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Jede Variable in C hat einen Typ, der bei der Deklaration gewählt wird und für ihre gesamte Lebensdauer feststeht. Der Typ entscheidet drei Dinge: wie viele Bytes die Variable belegt, wie diese Bytes gedeutet werden und welche Operationen auf ihr sinnvoll sind.

Die Typliste von C ist kurz. Die Komplexität steckt in den Modifikatoren.

Die vier Basistypen

  • char fasst ein Byte. Es wird für einzelne Zeichen ('A'), für die Bytes einer Zeichenkette und manchmal als winzige Ganzzahl benutzt.
  • int ist das Arbeitstier unter den Ganzzahltypen. Schleifenzähler, Größen, IDs.
  • float und double fassen reelle Zahlen. double hat etwa die doppelte Genauigkeit.
  • void ist in gewissem Sinne der vierte Typ, bedeutet aber „kein Wert" - du kannst keine void-Variable deklarieren, sondern es nur als Rückgabetyp einer Funktion, als leere Parameterliste oder als typlosen Zeiger benutzen.

Beachte das Suffix f bei 3.14f. Ohne es ist das Literal ein double, und es einem float zuzuweisen verliert still an Genauigkeit. Manche Compiler warnen davor.

Modifikatoren: short, long, unsigned

Die ganzzahligen Basistypen kommen mit Modifikatoren, die Größe oder Vorzeichen ändern.

Jeder Ganzzahltyp braucht seine eigene Formatangabe: %hd für short, %d für int, %ld für long, %lld für long long, %u für unsigned. Die falsche zu benutzen ist undefiniertes Verhalten, kein Rundungsfehler.

unsigned entfernt das Vorzeichenbit und verdoppelt den positiven Bereich. Ein unsigned int fasst 0 bis etwa 4,3 Milliarden statt -2,1 bis +2,1 Milliarden. Es ist die richtige Wahl für Dinge, die wirklich nicht negativ sein können - Größen, Byteanzahlen, Bitmuster - und eine Falle für alles, von dem unter null subtrahiert werden könnte.

signed ist die Voreinstellung für int, short, long und long long, du schreibst es also fast nie. Die eine Stelle, an der es zählt, ist char: Ob ein schlichtes char vorzeichenbehaftet oder vorzeichenlos ist, ist implementierungsabhängig, schreibe also signed char oder unsigned char, wenn das Vorzeichen zählt.

Größen: was du tatsächlich bekommst

Der C-Standard gibt Mindestgrößen vor, keine exakten. Auf jeder modernen 64-Bit-Maschine mit Linux, macOS oder Windows siehst du dies:

TypTypische GrößeTypischer Bereich
char1 Byte-128 bis 127 (oder 0 bis 255)
short2 Bytes-32.768 bis 32.767
int4 Bytes-2.147.483.648 bis 2.147.483.647
long8 Bytes (4 unter Windows)grob ±9,2 Trillionen
long long8 Bytesgrob ±9,2 Trillionen
float4 Bytes~7 signifikante Stellen
double8 Bytes~15 signifikante Stellen
long double16 Bytes (schwankt)mehr als double

Die long-Zeile ist die, die Leute erwischt: Unter Linux und macOS sind es 8 Bytes und unter 64-Bit-Windows 4 Bytes. Code, der annimmt, long könne einen 64-Bit-Wert fassen, ist nicht portabel. Nimm long long oder die Typen exakter Breite aus stdint.h (int32_t, uint64_t), wenn die Größe zur Anforderung gehört.

sizeof: den Compiler fragen

Rate nie eine Größe - miss sie:

sizeof ist ein Operator, keine Funktion, und es wird zur Übersetzungszeit ausgewertet. Es liefert einen Wert vom Typ size_t, der sich mit %zu ausgeben lässt.

sizeof(char) ist garantiert genau 1 - das ist die Definition eines Bytes in C. Alles andere wird daran gemessen.

limits.h und float.h

Die genauen Bereiche deines Compilers stehen als benannte Konstanten bereit:

Das sind die Werte, gegen die du vergleichst, wenn du wissen musst, ob eine Operation überläuft. if (a > INT_MAX - b) zu prüfen, bevor du a + b berechnest, ist der Weg, einen Überlauf zu erkennen, bevor er passiert - was zählt, denn einen vorzeichenbehafteten Überlauf kannst du hinterher nicht erkennen.

Ganzzahlüberlauf

Was passiert, wenn ein Wert den Bereich seines Typs überschreitet, hängt vollständig vom Vorzeichen ab.

Ein vorzeichenloser Überlauf ist definiert: Der Wert schlägt modulo 2^N um.

Der zweite Fall ist eine echte Fehlerquelle. Eine Schleife wie for (unsigned i = n - 1; i >= 0; i--) endet nie, denn ein vorzeichenloser Wert ist immer >= 0.

Ein vorzeichenbehafteter Überlauf ist undefiniertes Verhalten. Nicht „schlägt um" - undefiniert. Der Compiler darf annehmen, dass er nie passiert, und darauf aufbauend optimieren, was bedeutet, dass eine nachträglich geschriebene Überlaufprüfung gelöscht werden darf:

int sum = a + b;
if (sum < a) { /* der Compiler darf das vollständig entfernen */ }

Prüfe vorher, mit den Grenzwerten:

if (b > 0 && a > INT_MAX - b) {
    /* a + b würde überlaufen - behandle es */
}

Gleitkommagenauigkeit

float und double speichern Zahlen binär, und die meisten Dezimalbrüche haben keine exakte binäre Form - so wie 1/3 keine exakte dezimale Form hat.

Daraus folgt die Regel: Vergleiche Gleitkommawerte nie mit ==. Vergleiche stattdessen die absolute Differenz gegen eine kleine Toleranz.

Und benutze für Geld nie Gleitkommazahlen. Speichere Cent als Ganzzahl; ein long long in Cent ist exakt, wo ein double in Euro es nicht ist.

Einen Typ wählen

Eine kurze Entscheidungsliste, die den meisten Code abdeckt:

  • Ganze Zahlen: int, sofern du keinen Grund hast. Es ist der Typ, den die CPU am effizientesten behandelt, und der, um den herum alle Rechenregeln gebaut sind.
  • Alles über 2 Milliarden: long long oder int64_t aus stdint.h.
  • Größen, Längen, Array-Indizes aus sizeof oder strlen: size_t. Es ist vorzeichenlos und garantiert groß genug für jedes Objekt.
  • Dezimalzahlen: double. Nimm float nur, um in großen Arrays Speicher zu halbieren oder auf Embedded-Hardware ohne Einheit für doppelte Genauigkeit.
  • Einzelne Zeichen und rohe Bytes: char für Text, unsigned char für Binärdaten.
  • Wahr/falsch: bool aus stdbool.h - siehe Booleans in C.
  • Exakte Bitbreiten (Dateiformate, Netzprotokolle, Hardwareregister): stdint.h - uint8_t, int16_t, uint32_t und so weiter.

Typen mischen

Wenn du zwei verschiedene Typen in einem Ausdruck kombinierst, wandelt C sie hinter deinem Rücken um, bevor es rechnet. Das ist meist hilfreich und gelegentlich verheerend:

Das Erste ist Ganzzahldivision: Beide Operanden sind int, das Ergebnis ist also ein int und der Bruchteil fällt weg. Das Dritte ist schlimmer - einen vorzeichenbehafteten Wert mit einem vorzeichenlosen zu vergleichen wandelt den vorzeichenbehafteten in vorzeichenlos um und macht aus -1 eine riesige positive Zahl.

Diese Umwandlungsregeln und wie man sie mit expliziten Casts in den Griff bekommt, sind das Thema von Typumwandlung in C.

Häufig gestellte Fragen

Was sind die grundlegenden Datentypen in C?

Vier Basistypen: char für einzelne Zeichen und Bytes, int für ganze Zahlen, float und double für Dezimalzahlen. Modifikatoren ändern Größe und Vorzeichen - short, long, long long, signed und unsigned - und ergeben den vollständigen Satz.

Wie viele Bytes hat ein int in C?

Auf modernen Desktop- und Serversystemen fast immer 4 Bytes (32 Bit), was einen Bereich von etwa -2,1 Milliarden bis 2,1 Milliarden ergibt. Der Standard garantiert nur mindestens 2 Bytes, und 16-Bit-Mikrocontroller benutzen tatsächlich 2. Nimm sizeof(int), wenn du es sicher wissen musst.

Was ist der Unterschied zwischen float und double in C?

float hat 4 Bytes mit etwa 7 signifikanten Dezimalstellen; double hat 8 Bytes mit etwa 15. Double ist die Voreinstellung für Gleitkommaliterale und Mathematikfunktionen, und solange du nicht Millionen von Werten speicherst oder auf einen Embedded-Chip zielst, ist double die richtige Wahl.

Was passiert, wenn ein int in C überläuft?

Bei einem vorzeichenbehafteten int ist ein Überlauf undefiniertes Verhalten - der Compiler darf umschlagen, sättigen oder die Prüfung ganz wegoptimieren. Bei einem vorzeichenlosen int ist er vollständig definiert: Der Wert schlägt modulo 2^N um, UINT_MAX + 1 ist also 0. Verlass dich nie auf einen vorzeichenbehafteten Überlauf.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S