# 4.3 Eigene Datentypen

Quelle: https://inf.zone/lectures/4-memory/short-4-3-eigene-typen/

## Video

[Video ansehen (1080p)](https://videos.inf.zone/cf70e54f86beaf43/short-4-3-eigene-typen-1080p.mp4) · [Video (720p)](https://videos.inf.zone/cf70e54f86beaf43/short-4-3-eigene-typen-720p.mp4) · [Video (480p)](https://videos.inf.zone/cf70e54f86beaf43/short-4-3-eigene-typen-480p.mp4) · [Video auf YouTube](https://youtu.be/_PToIiV75hc)

## Hinweise zu diesem Video

**Korrekturen**

Die Korrekturen betreffen das Video. In den Folien zum Herunterladen sind sie eingearbeitet, soweit sie die Folien betreffen.

- Folie 12: Das Kennzeichen „M-XY-123“ hat acht Zeichen und braucht mit Nullterminator 9 Byte; in das Feld char plate[7] passen höchstens sechs Zeichen. Das Beispiel im Bild wäre also selbst ein Buffer Overflow.

## Material

- [Folien](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf)
- Folien und Transkript: unten auf dieser Seite

## Folien und Transkript

*Folientext aus den PDF-Folien, darunter jeweils der gesprochene Text des Videos. Der gesprochene Text ist maschinell transkribiert und nachkorrigiert, kann aber noch Fehler enthalten; im Video sprechen abwechselnd Prof und eine AI-Figur, die Sprecherwechsel sind nicht markiert. Die Zuordnung zu den Folien ist ungefähr. Die Zeitangaben verlinken auf die Stelle im Video (YouTube). Maßgeblich sind Video und Folien.*

### Folie 1 — Eigene Datentypen

[Folie 1 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=1)

#### Transkript

**[Video 00:00–00:35](https://www.youtube.com/watch?v=_PToIiV75hc&t=0)**

Dies ist Inf-Einf-B. Heute eigene Datentypen. Hallo, heute sprechen wir über benutzerdefinierte Datentypen in C. Ich finde es ja irgendwie faszinierend, wie Menschen sich mit so primitiven Datentypen wie int oder char zufriedengeben, wenn sie doch viel ausdrucksstärkere Typen erstellen könnten. Na, na, na, nicht so herablassend. Die grundlegenden Datentypen sind durchaus nützlich. Stimmt schon. Aber stell dir vor, du müsstest ein Autoverwaltungssystem nur mit Integern und einzelnen Zeichen programmieren. Das wäre wie, also wie wenn Menschen versuchen würden Pointer

**[Video 00:35–01:06](https://www.youtube.com/watch?v=_PToIiV75hc&t=35)**

Also, ich glaube, unsere Studierenden haben schon verstanden, worauf du hinauswillst. Fang doch einfach mal an. Wie Sie bereits wissen, arbeiten wir in C mit verschiedenen Datentypen wie int oder char.

### Folie 2

[Folie 2 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=2)

Das C-Schlüsselwort `typedef` ermöglicht es, Kurzformen oder alternative Namen für Datentypen zu erstellen.

Dadurch können wir es vermeiden, lange Typen wie `unsigned` `long` `int` jedes Mal komplett ausschreiben zu müssen.

Außerdem kann man komplexere Datentypen erstellen.

Die Grundidee ist, einen Typ zunächst zu definieren und ihm dann einen Alias zu geben.

#### Transkript

**[Video 00:35–01:06](https://www.youtube.com/watch?v=_PToIiV75hc&t=35)**

Aber manchmal möchten wir diese grundlegenden Typen erweitern oder umbenennen. Dafür gibt uns C das Schlüsselwort typedef. typedef ist gewissermaßen wie ein, nun ja, wie ein Übersetzer. Es erlaubt uns, einem existierenden Datentyp einen neuen Namen zu geben oder, und das ist noch spannender, komplexere Datentypen zu erschaffen und diese mit praktischen Namen zu versehen.

**[Video 01:06–01:26](https://www.youtube.com/watch?v=_PToIiV75hc&t=66)**

Stellen Sie sich vor, Sie haben einen sehr langen Typnamen wie unsigned long int, den Sie häufig verwenden müssen. Mit typedef können Sie diesem Typ einen kürzeren, aussagekräftigen Namen geben. Die Syntax von typedef ist recht einfach. Wir schreiben zunächst das Schlüsselwort typedef, gefolgt von dem ursprünglichen Typnamen, dem old name, und dann dem neuen Namen, den wir verwenden möchten.

**[Video 01:26–02:00](https://www.youtube.com/watch?v=_PToIiV75hc&t=86)**

Das Ganze wird mit einem Semikolon abgeschlossen. Hier sehen Sie ein klassisches Beispiel für typedef.

### Folie 3 — Syntax

[Folie 3 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=3)

```text
typedef <old name> <new name>;
```

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*

### Folie 4 — Syntax

[Folie 4 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=4)

```text
typedef <old name> <new name>;
typedef unsigned char byte;
byte buffer[1024];
```

#### Transkript

**[Video 01:26–02:00](https://www.youtube.com/watch?v=_PToIiV75hc&t=86)**

Wir definieren einen neuen Namen byte für den Typ unsigned char. Das ist besonders praktisch, wenn Sie mit Binärdaten arbeiten, da ein unsigned char genau ein Byte speichert. Statt also immer unsigned char buffer 256 schreiben zu müssen, können Sie jetzt einfach byte buffer 256 verwenden. Das macht den Code nicht nur kürzer, sondern vor allem auch lesbarer und aussagekräftiger. Schließlich verrät der Name byte direkt, wofür dieser Typ gedacht ist.

### Folie 5 — Syntax

[Folie 5 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=5)

```text
typedef <old name> <new name>;
typedef char* string;
string name;
```

#### Transkript

**[Video 01:26–02:00](https://www.youtube.com/watch?v=_PToIiV75hc&t=86)**

Hier sehen Sie ein weiteres sehr nützliches Beispiel für typedef.

**[Video 02:00–02:37](https://www.youtube.com/watch?v=_PToIiV75hc&t=120)**

Wir definieren einen Typ namens String, der eigentlich ein Pointer auf char ist. In C ist ein String ja nichts anderes als ein Pointer auf das erste Zeichen einer Zeichenkette. Mit dieser Definition können wir nun string name schreiben, anstatt char Stern name. Das macht unseren Code nicht nur eleganter, sondern vor allem auch verständlicher für Programmierer, die von anderen Programmiersprachen kommen, wo der Typ String bereits existiert. Wenn Sie sich schon einmal gefragt haben, warum wir in unseren Programmen den Typ String nur verwenden können, wenn wir cs50.h einbinden, genau das ist der Grund. In dieser Headerdatei steht die Zeile typedef

**[Video 02:37–02:58](https://www.youtube.com/watch?v=_PToIiV75hc&t=157)**

char\* string. Dadurch konnten wir ein paar Besonderheiten von Strings in C am Anfang verbergen.

### Folie 6 — Strukturen

[Folie 6 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=6)

```text
struct car
{
    int year;
    char model[10];
    char plate[7];
    int odometer;
    double engine_size;
};
typedef struct car car_t;
```

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*

### Folie 7 — Strukturen

[Folie 7 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=7)

```text
struct car
{
    int year;
    char model[10];
    char plate[7];
    int odometer;
    double engine_size;
};
typedef struct car car_t;
```

```text
 

// Variable-Deklaration
struct car mycar;       // ohne typedef
car_t mycar;            // mit typedef

// Zugriff auf Felder
mycar.year = 2011;
strcpy(mycar.plate, "CS50");
mycar.odometer = 50505;
```

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*

### Folie 8 — Strukturen: Kurzschreibweise

[Folie 8 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=8)

```text
typedef struct car
{
    int year;
    char model[10];
    char plate[7];
    int odometer;
    double engine_size;
}
car_t;
```

#### Transkript

**[Video 02:37–02:58](https://www.youtube.com/watch?v=_PToIiV75hc&t=157)**

In echtem C müssten Sie entweder diese typedef-Definition selbst vornehmen oder eben direkt mit char\* arbeiten. Wir haben also wieder ein Geheimnis gelüftet. Die Stützräder, auf die Sie ganz am Anfang noch angewiesen waren, werden weniger. Kommen wir nun zu einem besonders wichtigen Anwendungsfall von typedef.

**[Video 02:58–03:32](https://www.youtube.com/watch?v=_PToIiV75hc&t=178)**

eine Struct oder auf Deutsch eine Struktur ist ein zusammengesetzter Datentyp, der mehrere Variablen verschiedener Typen zu einer Einheit zusammenfasst. In unserem Beispiel definieren wir eine Struct namens car, die verschiedene Eigenschaften eines Autos speichert: das Baujahr als int, das Modell als Zeichenkette mit maximal neun Zeichen plus Null-Terminator, das Kennzeichen mit maximal sechs Zeichen plus Null-Terminator, den Kilometerstand als Integer und die Motorgröße als Double.

### Folie 9 — Vorteil von typedef

[Folie 9 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=9)

```text
// Ohne typedef - umständlich:
struct car
{
    int year;
    char model[10];
    char plate[7];
    int odometer;
    double engine_size;
};
struct car mycar; // struct muss immer angegeben werden

// Mit typedef - elegant:
typedef struct car car_t;
car_t mycar; // kürzere Schreibweise
```

#### Transkript

**[Video 02:58–03:32](https://www.youtube.com/watch?v=_PToIiV75hc&t=178)**

Ohne typedef müssten wir jedes Mal struct car schreiben, wenn wir eine Variable dieses Typs deklarieren wollen. Das ist ziemlich umständlich. Mit der Zeile

**[Video 03:32–04:04](https://www.youtube.com/watch?v=_PToIiV75hc&t=212)**

typedef struct car car\_t können wir stattdessen einfach car\_t verwenden. Das Unterstrich T am Ende ist übrigens eine häufig verwendete Konvention in C, die darauf hinweist, dass es sich um einen typedef-Namen handelt. Vielleicht sollten wir den Studierenden kurz zeigen, wie der Unterschied in der Verwendung eigentlich konkret aussieht. Ja, schauen wir uns den praktischen Unterschied an. Ohne typedef müssen wir schreiben struct car mycar, um eine Variable vom Typ unserer Auto-Struct zu erstellen. Mit typedef können wir einfach car\_t mycar schreiben. Viel kürzer und übersichtlicher.

**[Video 04:04–04:28](https://www.youtube.com/watch?v=_PToIiV75hc&t=244)**

Der Zugriff auf die einzelnen Felder erfolgt dann in beiden Fällen gleich mit dem Punktoperator. Wir können zum Beispiel das Baujahr mit mycar.year gleich 2011 setzen. Für Zeichenketten wie das Kennzeichen verwenden wir strcpy, da wir Strings in C ja nicht direkt zuweisen können. Moment mal, warum verwenden wir hier eigentlich strcpy und nicht einfach eine direkte Zuweisung? Na, weil wir in C Arrays und damit auch Strings nicht direkt zuweisen können.

**[Video 04:28–05:04](https://www.youtube.com/watch?v=_PToIiV75hc&t=268)**

mycar.plate = CS50 würde beim Kompilieren einen Fehler erzeugen. Stattdessen müssen wir strcpy verwenden, das die Zeichen einzeln kopiert. Also weiter mit Structs. Da Structs so häufig mit typedef verwendet werden, gibt es eine elegantere Möglichkeit, beides zu kombinieren. Statt die Struct erst zu definieren und dann typedef zu verwenden, können wir beides in einem Schritt erledigen. Wir beginnen mit typedef, definieren dann die komplette Struct und am Ende statt einem Semikolon schreiben wir direkt den neuen Namen, also car\_t. Das Ergebnis ist genau das gleiche wie bei unserer vorherigen Methode, aber der Code ist kompakter und übersichtlicher.

**[Video 05:04–05:40](https://www.youtube.com/watch?v=_PToIiV75hc&t=304)**

Der alte Name, in diesem Fall struct car, und der neue Name car\_t bezeichnen dann exakt den gleichen Typ. Sie können beide Schreibweisen verwenden, aber car\_t ist natürlich kürzer und eleganter. Das car nach struct benötigen wir aber eigentlich gar nicht, oder? Ja, das car ist tatsächlich optional. Sie können das weglassen und eine sogenannte anonyme Struktur erstellen. In der ersten Variante geben wir der Struktur den Namen car. Das bedeutet, Sie könnten theoretisch sowohl struct car als auch car\_t verwenden. In der zweiten Variante verzichten wir auf den Namen nach struct.

**[Video 05:40–06:00](https://www.youtube.com/watch?v=_PToIiV75hc&t=340)**

Die Struktur existiert dann nur unter dem Namen car unterstrich t. Das macht den Code noch etwas schlanker. Und wenn Sie sicher sind, dass Sie die Struktur nur über den typedef-Namen ansprechen wollen, ist das eine saubere Lösung. Also noch einmal zusammenfassend, warum typedef bei Strukturen so nützlich ist. Ohne typedef müssen Sie jedes Mal struct car schreiben, wenn Sie eine Variable erstellen wollen.

**[Video 06:00–06:36](https://www.youtube.com/watch?v=_PToIiV75hc&t=360)**

Das macht den Code unnötig lang und schwerer lesbar. Mit typedef können Sie stattdessen einfach car\_t schreiben. Das ist nicht nur kürzer, sondern macht den Code auch übersichtlicher. Besonders bei komplexeren Programmen, wo Sie viele Variablen dieses Typs erstellen, macht sich dieser Vorteil deutlich bemerkbar. Das Prinzip ist dasselbe wie bei unserem früheren String-Beispiel. typedef macht den Code prägnanter und aussagekräftiger. In der Praxis sieht man die Version mit typedef häufiger, oder? Absolut. In modernem C-Code ist es quasi Standard, Strukturen mit typedef zu definieren. Es ist einer dieser Fälle, wo eine kleine syntaktische Verbesserung zu deutlich besserem Code führt.

**[Video 06:36–07:12](https://www.youtube.com/watch?v=_PToIiV75hc&t=396)**

So, damit haben wir die wichtigsten Grundlagen zu typedefs und Strukturen behandelt.

### Folie 10

[Folie 10 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=10)

E X T R A S I N 3 M I N U T E N FRAGEN – ANTWORTEN – RÄTSEL UND KURZE ZUSAMMENFASSUNG

#### Transkript

> Zuordnung unsicher: wenige gemeinsame Textmerkmale; anhand der benachbarten Folien eingeordnet.

**[Video 06:36–07:12](https://www.youtube.com/watch?v=_PToIiV75hc&t=396)**

Moment, ich sehe da noch einige fragende Gesichter.

### Folie 11 — Unterschiede bei Strings

[Folie 11 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=11)

```text
// Variante 1: Struktur mit strings (char*)
typedef struct
{
   string  name;   // entspricht char*
   string  number;  // entspricht char*
}
person;

// Variante 2: Struktur mit char arrays
typedef struct
{
    char model[10];  // fest eingebautes Array
    char plate[7];  // fest eingebautes Array
}
car;
```

#### Transkript

**[Video 06:36–07:12](https://www.youtube.com/watch?v=_PToIiV75hc&t=396)**

Vielleicht nehmen wir uns noch die drei extra Minuten Zeit. Mir ist nämlich aufgefallen, dass wir vorhin bei der Car-Struktur strcpy verwendet haben, aber in der Vorlesung konnten wir beim Telefonbuchbeispiel die Strings direkt zuweisen. Ich würde vermuten, das wird einige verwirren. Ah, sehr gute Beobachtung. Das ist in der Tat ein wichtiger Unterschied, den wir unbedingt klären sollten. Lassen Sie uns das anhand einer Gegenüberstellung verdeutlichen. Der fundamentale Unterschied liegt in der Art, wie diese beiden Strukturen im Speicher organisiert sind.

**[Video 07:12–07:34](https://www.youtube.com/watch?v=_PToIiV75hc&t=432)**

Bei der Person-Struktur speichern wir nur zwei Pointer, also Zeiger auf die eigentlichen Zeichenketten, die woanders im Speicher liegen. Kannst du das vielleicht irgendwie visualisieren? Vielleicht mit einer Speicherdarstellung? Dann würde das vielleicht bisschen klarer werden. Hier sehen Sie den entscheidenden Unterschied: Bei der Person-Struktur speichern wir nur die Adressen, wo die Strings zu finden sind. Der eigentliche Text liegt woanders im Speicher.

**[Video 07:34–08:12](https://www.youtube.com/watch?v=_PToIiV75hc&t=454)**

Der Compiler legt einen Namen dann irgendwo im Speicher ab und setzt den Name-Pointer darauf. Und bei der Car-Struktur? Bei der Car-Struktur sind die Arrays fest eingebaut, quasi einbetoniert in die Struktur selbst. Wenn wir da einen neuen Text reinschreiben wollen, müssen wir ihn Zeichen für Zeichen an die richtige Stelle kopieren. Deshalb brauchen wir strcpy. Das erklärt auch den unterschiedlichen Speicherbedarf, oder? Genau. Bei der Person-Struktur brauchen wir nur Platz für zwei Pointer, auf einem vierundsechzig-Bit-System also sechzehn Bytes. Bei der Car-Struktur müssen wir den kompletten Platz für die Arrays reservieren, also siebzehn Bytes für die beiden Arrays zusammen. Wir sollten uns noch die praktischen Konsequenzen dieser beiden Ansätze anschauen.

**[Video 08:12–08:48](https://www.youtube.com/watch?v=_PToIiV75hc&t=492)**

Bei der Person-Struktur mit Strings können wir Zeichenketten beliebiger Länge zuweisen. Der Pointer zeigt einfach auf den neuen String, egal wie lange er ist. Das ist sehr flexibel. Bei der Car-Struktur mit festen Arrays müssen wir dagegen immer aufpassen, dass wir die vorgegebene Länge nicht überschreiten. Wenn wir versuchen, Mercedes-Benz in ein Array der Länge zehn zu kopieren, bekommen wir einen Buffer Overflow. Das kann zu schwerwiegenden Problemen führen. Das klingt ja so, als wäre die Variante mit Strings immer besser, oder? Nicht unbedingt. Die Array-Variante hat auch Vorteile. Sie ist vorhersehbarer im Speicherverbrauch und wir können uns sicher sein, dass die Daten wirklich zusammenhängend im Speicher liegen.

**[Video 08:48–09:07](https://www.youtube.com/watch?v=_PToIiV75hc&t=528)**

Außerdem verhindert sie, dass wir versehentlich Null-Pointer erzeugen, was bei der String-Variante durchaus passieren kann. In unserem Telefonbuch-Beispiel war die String-Variante die bessere Wahl, weil wir nicht wissen, wie lang die Namen und Telefonnummern sein werden. Bei der Auto-Struktur dagegen wissen wir, dass Kennzeichen eine standardisierte Länge haben. Da macht ein Array mehr Sinn.

**[Video 09:07–09:38](https://www.youtube.com/watch?v=_PToIiV75hc&t=547)**

Tja, wie so oft in der Programmierung gibt es nicht die eine perfekte Lösung. Es ist wie beim Autokauf. Manchmal braucht man einen flexiblen Kombi für variable Ladung. Das wären unsere Char-Pointer, also Strings, und manchmal einen Sportwagen mit fest eingebauten Sitzen. Unsere Arrays. Hat dir eigentlich schon mal jemand gesagt, dass deine Analogien manchmal echt speziell sind? Ich denke, das ist der Moment, wo wir einfach unsere Zusammenfassung einblenden. Dies war Inf-Einf-B.

### Folie 12 — Unterschiede bei Strings

[Folie 12 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=12)

```text
Person-Struktur:
+-----------------+     +------------------+
|  name (8 Byte)  | --> | "Dominik\0"      |
+-----------------+     +------------------+
| number (8 Byte) | --> | "+49-951...\0"   |
+-----------------+     +------------------+

Car-Struktur:
+--------------------------------+
| model: "BMW\0     " (10 Byte)  |
+--------------------------------+
| plate: "BA-X-1\0  " (7 Byte)   |
+--------------------------------+
```

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*

### Folie 13

[Folie 13 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=13)

```text
// Mit char*:
typedef struct
{
    string name;
    string number;
} person;

person p;
p.name = "Kurzer Name";      // Funktioniert!
p.name = "Ein sehr sehr sehr langer Name";  // Funktioniert auch!

car c;
strcpy(c.model, "BMW");      // Funktioniert!
strcpy(c.model, "Mercedes-Benz");  // Buffer Overflow!
```

```text
// Mit Arrays
typedef struct
{
    char model[10];
    char plate[7];
} car;
```

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*

### Folie 14 — typedef ermöglicht das Erstellen von Aliasnamen

[Folie 14 als PDF](https://inf.zone/download/lectures/4-memory/4.3-eigene-typen.pdf#page=14)

Strings (char\*) erlauben flexible Längenverwaltung

für Datentypen

Besonders nützlich bei der Arbeit mit Strukturen

Character-Arrays haben feste, vorhersagbare Größe

(structs)

Strukturnamen nach

Die Wahl zwischen string

und char\[\] hängt vom

struct sind optional

Anwendungsfall ab

> Bildinhalte sind nicht transkribiert; siehe Originalfolie.

#### Transkript

*Kein Transkriptabschnitt eindeutig dieser Folie zugeordnet. Möglicherweise eine Aufbau-/Grafikfolie oder eine Abweichung zwischen PDF und Video.*
