struct: Daten bündeln
Eine struct fasst zusammengehörige Variablen verschiedener Typen unter einem Namen zusammen:
#include <stdio.h>
#include <string.h>
struct Person {
char name[32];
int alter;
double gewicht;
};
int main(void) {
struct Person mia = { "Mia", 17, 58.5 };
struct Person tom = { .name = "Tom", .alter = 19 }; // benannte Initialisierung, Rest = 0
mia.alter++;
strcpy(tom.name, "Tom K.");
printf("%s %d %.1f\n", mia.name, mia.alter, mia.gewicht);
printf("%s %d %.1f\n", tom.name, tom.alter, tom.gewicht);
struct Person kopie = mia; // Struktur komplett kopieren
kopie.alter = 99;
printf("%d %d\n", mia.alter, kopie.alter);
printf("Größe: %zu\n", sizeof(struct Person));
return 0;
}Mia 18 58.5 Tom K. 19 0.0 18 99 Größe: 48
Mit typedef bekommt der Typ einen kürzeren Namen:
#include <stdio.h>
#include <math.h>
typedef struct {
double x, y;
} Punkt;
typedef struct {
Punkt links_oben;
double breite, hoehe;
} Rechteck;
double abstand(Punkt a, Punkt b) { return hypot(a.x - b.x, a.y - b.y); }
double flaeche(const Rechteck *r) { return r->breite * r->hoehe; } // -> bei Zeigern
int main(void) {
Punkt a = {0, 0}, b = {3, 4};
Rechteck r = { {1, 2}, 5, 3 };
printf("%.1f %.1f %.1f\n", abstand(a, b), flaeche(&r), r.links_oben.y);
return 0;
}5.0 15.0 2.0
Große Strukturen übergibst du als const Struktur * (kein Kopieren); p->feld ist die Kurzform von (*p).feld. (Zum Linken von math.h kann -lm nötig sein.)
Arrays von Strukturen
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct { char name[16]; int punkte; } Spieler;
static int nach_punkten(const void *a, const void *b) {
return ((const Spieler *) b)->punkte - ((const Spieler *) a)->punkte; // absteigend
}
int main(void) {
Spieler liste[] = { {"Mia", 120}, {"Tom", 95}, {"Zoe", 210} };
int n = sizeof liste / sizeof liste[0];
qsort(liste, n, sizeof liste[0], nach_punkten);
for (int i = 0; i < n; i++) printf("%d. %-4s %3d\n", i + 1, liste[i].name, liste[i].punkte);
return 0;
}1. Zoe 210 2. Mia 120 3. Tom 95
enum: benannte Konstanten
#include <stdio.h>
enum Ampel { ROT, GELB, GRUEN }; // 0, 1, 2
typedef enum { MO = 1, DI, MI, DO, FR } Tag; // 1, 2, 3, ...
const char *name(enum Ampel a) {
switch (a) {
case ROT: return "rot";
case GELB: return "gelb";
case GRUEN: return "grün";
}
return "?";
}
int main(void) {
enum Ampel a = GELB;
Tag t = MI;
printf("%s %d %d %d\n", name(a), a, t, FR);
return 0;
}gelb 1 3 5
union: ein Speicherplatz, mehrere Sichten
Alle Felder einer union liegen am selben Speicherplatz. Es ist nur eines davon gleichzeitig gültig. Üblich ist die Kombination mit einem Kennzeichen (tagged union):
#include <stdio.h>
typedef struct {
enum { ZAHL, TEXT } art;
union { int zahl; const char *text; } wert;
} Wert;
void zeige(Wert w) {
if (w.art == ZAHL) printf("Zahl %d\n", w.wert.zahl);
else printf("Text %s\n", w.wert.text);
}
int main(void) {
Wert a = { ZAHL, .wert.zahl = 42 };
Wert b = { TEXT, .wert.text = "Hallo" };
zeige(a); zeige(b);
printf("%zu\n", sizeof(Wert));
return 0;
}Zahl 42 Text Hallo 16
Bitfelder und Ausrichtung
Der Compiler fügt zwischen Feldern oft Füllbytes (Padding) ein, damit Felder an passenden Adressen liegen. Die Reihenfolge der Felder beeinflusst die Größe:
#include <stdio.h>
#include <stddef.h>
struct Schlecht { char a; int b; char c; }; // a, 3 Füllbytes, b, c, 3 Füllbytes
struct Besser { int b; char a; char c; };
int main(void) {
printf("%zu %zu\n", sizeof(struct Schlecht), sizeof(struct Besser));
printf("%zu %zu\n", offsetof(struct Schlecht, b), offsetof(struct Schlecht, c));
return 0;
}12 8 4 8
Verkettete Liste: Struktur mit Zeiger auf sich selbst
#include <stdio.h>
#include <stdlib.h>
typedef struct Knoten {
int wert;
struct Knoten *weiter;
} Knoten;
Knoten *vorne(Knoten *kopf, int wert) {
Knoten *k = malloc(sizeof *k);
if (!k) return kopf;
k->wert = wert;
k->weiter = kopf;
return k;
}
int main(void) {
Knoten *liste = NULL;
for (int i = 1; i <= 4; i++) liste = vorne(liste, i * 10);
for (Knoten *k = liste; k; k = k->weiter) printf("%d -> ", k->wert);
printf("NULL\n");
while (liste) { Knoten *n = liste->weiter; free(liste); liste = n; } // aufräumen
return 0;
}40 -> 30 -> 20 -> 10 -> NULL
Merke
structbündelt Felder; Zugriff mit.bzw.->bei Zeigerntypedefgibt Typen kürzere Namen; Strukturen lassen sich kopieren und per Zeiger übergebenenumfür benannte Ganzzahl-Konstanten;unionteilt sich einen Speicherplatz- Füllbytes machen Strukturen oft größer, als die Felder vermuten lassen
- Verkettete Strukturen entstehen mit Zeigern auf den eigenen Typ
Aufgabe
Lege eine Struktur Buch (Titel, Autor, Jahr) an, speichere drei Bücher in einem Array und sortiere sie nach Jahr.