C ist statisch typisiert: Jede Variable hat einen festen Typ, der bestimmt, wie viel Speicher sie braucht.
Ganzzahlen und Kommazahlen
| Typ | typische Größe | Bereich |
|---|---|---|
char | 1 Byte | ein Zeichen oder -128 bis 127 |
short | 2 Byte | ±32.767 |
int | 4 Byte | ±2,1 Milliarden |
long | 4 oder 8 Byte | systemabhängig |
long long | 8 Byte | ±9,2 · 10¹⁸ |
unsigned ... | wie oben | nur ≥ 0, doppelt so groß |
float | 4 Byte | ca. 7 Stellen |
double | 8 Byte | ca. 15 Stellen (Standard) |
_Bool / bool | 1 Byte | 0 oder 1 (<stdbool.h>) |
Die Größen hängen vom System ab. Für feste Größen gibt es <stdint.h>: int8_t, uint8_t, int16_t, int32_t, int64_t, uint64_t, sowie size_t für Größen und Indizes.
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
int main(void) {
int alter = 17;
unsigned int zaehler = 3000000000u;
long long gross = 9000000000LL;
double pi = 3.14159265358979;
char buchstabe = 'A';
bool fertig = true;
uint8_t byte = 255;
printf("%d %u %lld %.5f %c %d %d\n", alter, zaehler, gross, pi, buchstabe, fertig, byte);
printf("Größen: char %zu, short %zu, int %zu, long %zu, long long %zu, double %zu, Zeiger %zu\n",
sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long), sizeof(double), sizeof(void *));
printf("INT_MAX = %d, INT_MIN = %d\n", INT_MAX, INT_MIN);
return 0;
}17 3000000000 9000000000 3.14159 A 1 255 Größen: char 1, short 2, int 4, long 8, long long 8, double 8, Zeiger 8 INT_MAX = 2147483647, INT_MIN = -2147483648
sizeof liefert die Größe in Bytes. Ein char ist technisch eine kleine Ganzzahl: 'A' ist 65.
Konstanten
#include <stdio.h>
#define MWST 0.19 /* Makro (Textersetzung, kein Typ) */
enum { MAX_LAENGE = 10 }; /* Aufzählungskonstante */
int main(void) {
const int ANZAHL = 5; /* typisierte Konstante */
double netto = 100.0;
printf("%.2f %d %d\n", netto * (1 + MWST), ANZAHL, MAX_LAENGE);
return 0;
}119.00 5 10
Schreibe Konstanten meist als const oder enum. #define kennt keine Typen und kann zu Überraschungen führen.
Ganzzahldivision, Umwandlung und Überlauf
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("%d %f %f\n", 7 / 2, 7 / 2.0, (double) 7 / 2); // 3, 3.5, 3.5
printf("%d %d\n", 7 % 3, -7 % 3); // Rest, Vorzeichen folgt dem Dividenden
int i = 3.99; // Nachkommastellen fallen weg
printf("%d\n", i);
unsigned char u = 255;
u++; // unsigned: definierter Überlauf (Wrap-around)
printf("%d\n", u);
char c = 'a' + 1;
printf("%c %d\n", c, c);
printf("%d\n", (int) 'A' + 1);
return 0;
}3 3.500000 3.500000 1 -1 3 0 b 98 66
Initialisieren!
Lokale Variablen haben ohne Anfangswert einen zufälligen Inhalt (was gerade im Speicher stand). Initialisiere immer:
#include <stdio.h>
int main(void) {
int a = 0;
int b = 5, c = 7;
double d = 0.0;
int feld[3] = {0}; // alle Elemente 0
printf("%d %d %d %.1f %d\n", a, b, c, d, feld[2]);
return 0;
}0 5 7 0.0 0
Gültigkeitsbereich und Lebensdauer
| Art | Gültig | Lebt |
|---|---|---|
| lokale Variable | im Block { } | bis zum Blockende (Stack) |
| globale Variable | im ganzen Programm | ganze Laufzeit (anfangs 0) |
static lokal | im Block | ganze Laufzeit, behält den Wert |
#include <stdio.h>
int zaehler_global = 0;
void zaehle(void) {
static int aufrufe = 0; // wird nur einmal initialisiert
int lokal = 0;
aufrufe++; lokal++; zaehler_global++;
printf("static %d, lokal %d, global %d\n", aufrufe, lokal, zaehler_global);
}
int main(void) {
zaehle(); zaehle(); zaehle();
return 0;
}static 1, lokal 1, global 1 static 2, lokal 1, global 2 static 3, lokal 1, global 3
Globale Variablen vermeidest du am besten: Sie machen Programme schwer verständlich.
Merke
- Typen:
char,int,long long,float,double,bool,unsigned; feste Größen aus<stdint.h> sizeofliefert die Größe in Bytes- Ganzzahldivision schneidet ab;
7 / 2.0rechnet als Kommazahl - Vorzeichenbehafteter Überlauf ist undefiniertes Verhalten
- Variablen immer initialisieren;
conststatt Magic Numbers staticlokal behält den Wert zwischen Aufrufen
Aufgabe
Gib die Größe und den Wertebereich der Typen int, unsigned int und long long auf deinem System aus.