# 4.2 Pointer

Quelle: https://inf.zone/lectures/4-memory/short-4-2-pointer/

## Video

[Video ansehen (1080p)](https://videos.inf.zone/bb00b9a9d66e9cf6/short-4-2-pointer-1080p.mp4) · [Video (720p)](https://videos.inf.zone/bb00b9a9d66e9cf6/short-4-2-pointer-720p.mp4) · [Video (480p)](https://videos.inf.zone/bb00b9a9d66e9cf6/short-4-2-pointer-480p.mp4) · [Video auf YouTube](https://youtu.be/FN2XlhueoQ0)

## Erratum

Folie 27 enthält im Video einen Fehler. Dort endet einer der dargestellten Strings in der Speicher-Abbildung mit `\n` – an dieser Stelle sollte jedoch wie beim anderen String ein `\0` stehen. In den Folien wurde dieser Fehler bereits korrigiert.

## Hinweise zu diesem Video

**Korrekturen**

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

- Folie 19: Der Kommentar „Ändert x und c“ stimmt nicht. Die Zuweisung \*pc = &#39;A&#39; ändert nur c; x enthält eine Kopie des alten Werts und bleibt unverändert.
- Folie 26: Die beiden gleichen Literale liegen bei üblichen Compilern an derselben Adresse, das Programm gibt dann „Gleich“ aus. Die Aussage der Folie bleibt richtig: == vergleicht Adressen, für den Inhalt braucht man strcmp.

## Material

- [Folien](https://inf.zone/download/lectures/4-memory/4.2-pointer.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 — Pointer

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

#### Transkript

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

Dies ist Inf-Einf-B. Heute Pointer. Ah, heute sprechen wir über eines meiner Lieblingsthemen in C. Pointer. Na, da ist ja jemand motiviert.

### Folie 2

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

Pointer (deutsch: Zeiger) bieten eine alternative Möglichkeit, Daten zwischen Funktionen auszutauschen.

Bisher haben wir alle Daten als Werte übergeben (by value), mit einer Ausnahme (Arrays). Bei der Wertübergabe wird nur eine Kopie der Daten weitergegeben.

Mit Pointern können wir die tatsächliche Variable selbst übergeben. Das bedeutet, dass Änderungen in einer Funktion sich auf eine andere Funktion auswirken können.

Vorher war das nicht möglich!

#### Transkript

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

Aber Vorsicht, damit tun sich viele, die C lernen, echt anfangs schwer. Also bitte, es ist doch ganz einfach. Ein Pointer ist nichts anderes als eine Adresse. Was kann daran schwer sein? Na ja, man hat ab jetzt halt zwei verschiedene Sachen, die man in einer Variable speichern kann. Und es gibt schon einige Sonderfälle, zum Beispiel Arrays. Aber das ist doch alles wirklich clever umgesetzt.

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

Das müsst ihr euch Menschen doch gefallen. Aber keine Sorge, ich werde es Schritt für Schritt erklären. Keine Angst, Pointer sind zwar echt herausfordernd, aber sie sind durchaus auch beherrschbar. Genau. Und um es gleich praktisch zu machen, stellen Sie sich vor, Sie haben eine Variable im Speicher. Moment, vielleicht sollten wir erst mal ein bisschen den Kontext klären, oder? Also gut, Menschen und ihr Bedürfnis nach Kontext. Beginnen wir mit den Grundlagen. Lassen Sie uns zunächst verstehen, was man mit so einem Pointer, auf Deutsch sagt man manchmal auch Zeiger, machen kann. Wenn wir bisher Daten zwischen Funktionen ausgetauscht haben.

**[Video 01:08–01:34](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=68)**

Wurde immer nur eine Kopie weitergegeben. Das bedeutet, wenn eine Funktion etwas an den Daten ändert, hat das keine Auswirkung auf die Originaldaten. Ein gutes Beispiel wäre vielleicht eine Funktion, die den Inhalt von zwei übergebenen Parametern vertauschen soll. Genau. Ohne Pointer würde das nicht gehen. Die Funktion würde nur mit Kopien arbeiten und die Originalvariablen würden sich gar nicht ändern. Aber mit Pointern geht das ganz einfach. Schau mal.

**[Video 01:34–02:06](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=94)**

Also grundsätzlich ist es ja gut, mit einem Beispiel anzufangen, aber in dem Fall vielleicht nicht. Ohne zu wissen, was man da tut, sind die ganzen Zeichen garantiert total verwirrend.

### Folie 3

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

```c
#include <stdio.h>

void tausche(int *i, int *j)
{
    int temp = *j;
   * j = *i;
   * i = temp;
}

int main(void)
{
    int i = 5, j = 10;
    tausche(&i, &j);
    printf("%i - %i\n", i, j); // gibt 10 - 5 aus
}
```

#### Transkript

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

### Folie 4

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

Bevor wir in die Details von Pointern einsteigen, sollten wir uns ansehen, wie der Speicher in einem Rechner funktioniert.

SpeicherGrundlagen

Jede Datei auf Ihrem Computer liegt auf einer Festplatte (HDD, hard-disk drive) oder SSD (solid-state disk) mit Platz für viele Gigabyte (GB) an Daten.

Solche Platten bieten nur Speicherplatz; direktes Arbeiten mit Dateien ist dort nicht möglich. Datenmanipulation und nutzung findet nur im Arbeitsspeicher (RAM, random access memory) statt. Deshalb müssen wir Daten dorthin bewegen, wenn wir sie benutzen wollen.

Der Arbeitsspeicher (z.B. 16 GB groß) ist im Prinzip ein großes Array aus Bytes.

#### Transkript

**[Video 01:34–02:06](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=94)**

Stimmt. Wir sollten erst einmal erklären, wie die Situation im Speicher des Computers eigentlich aussieht. Jede Datei auf dem Computer, sei es ein Programm, ein Dokument oder ein Bild, liegt zunächst auf der Festplatte. Wir sagen auch heute meist noch Festplatte. Damit kann entweder eine HDD gemeint sein, also eine Harddisk mit Magnetplatten, die sich drehen, oder eine moderne SSD, also eine Solid State Disk.

**[Video 02:06–02:41](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=126)**

In einer SSD werden die Daten in Flash-Speicherchips gespeichert, ähnlich wie auf einem USB-Stick. Aber diese Speichermedien sind nur passive Lagerstätten. Ja, so wie ein Bücherregal halt. Man kann die Bücher zwar dort aufbewahren, aber nicht direkt drin lesen. Nun ja, es ist schon etwas komplexer. Aber für Menschen mag dieser Vergleich hilfreich sein. Der eigentlich interessante Teil ist der Arbeitsspeicher, der RAM. Das steht für Random Access Memory, was bedeutet, dass wir in diesem Speicher die Möglichkeit haben, auf alle darin gespeicherten Daten ohne große Verzögerung zuzugreifen. Hier findet die echte Arbeit statt.

**[Video 02:41–03:02](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=161)**

Der RAM ist wie ein riesiges Array aus Bytes, jedes exakt acht Bit breit. Wenn wir mit verschiedenen Datentypen arbeiten, belegen diese unterschiedlich viel Platz im Speicher.

### Folie 5

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

Datentyp Größe (Byte)

int 4

char 1

float 4

double 8

long long 8

string ???

#### Transkript

**[Video 02:41–03:02](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=161)**

Ein einzelnes Zeichen, also ein char, braucht genau ein Byte. Ein int hingegen benötigt vier Bytes. Vielleicht sollten wir kurz erklären, warum diese Größen eigentlich im Hinblick auf unser Thema, das sind ja die Pointer.

**[Video 03:02–03:37](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=182)**

Wichtig sind. Ah ja, für Menschen ist das vermutlich nicht sofort ersichtlich. Die verschiedenen Größen sind entscheidend, wenn wir später mit Pointern durch den Speicher wandern.

### Folie 6 — Speicher als Array

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

Zurück zur Vorstellung vom Speicher als großes Array aus Byte-großen Zellen.

Wie bei Arrays, die wir bereits kennen, erlaubt dies direkten Zugriff.

Wir können einzelne Elemente des Arrays durch ihren Index ansprechen
- darüber haben wir direkten Zugriff auf jedes beliebige Element (sog. random access; anders als bei einer verketteten Liste, später mehr dazu).

Analog dazu hat jede Stelle im Speicher eine Adresse.

#### Transkript

**[Video 03:02–03:37](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=182)**

Jeder Datentyp hat seinen eigenen Platzbedarf und unsere Pointer müssen das berücksichtigen. Erinnern wir uns an Arrays. Sie ermöglichen uns den direkten Zugriff auf jedes Element über seinen Index. Der Computerspeicher funktioniert ganz ähnlich. Er ist im Grunde ein riesiges Array von Bytes und jedes Byte hat seine eigene Adresse. Genau wie bei einer Hausnummer in einer langen Straße.

### Folie 7 — Beispiel

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

```text
H                      65
```

0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF 0x10 0x11 0x12 0x13

```text
char c = 'H';
int speedlimit = 65;
```

POINTER SIND NUR ADRESSEN!

#### Transkript

**[Video 03:02–03:37](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=182)**

Lassen Sie uns ein konkretes Beispiel anschauen. Nehmen wir an, wir deklarieren zwei Variablen, einen char

**[Video 03:37–04:14](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=217)**

c, in den wir ein H speichern und eine Variable speedlimit, in die wir die Zahl 65 schreiben. Der Compiler weist diesen Variablen bestimmte Stellen im Speicher zu. Das H belegt ein einzelnes Byte, während der Integer speedlimit vier Bytes benötigt. Wichtig ist hier zu verstehen, dass wir die genauen Stellen, also die Adressen im Speicher, gar nicht vorhersagen können.

### Folie 8

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

```text
       k
int k;
```

#### Transkript

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

### Folie 9

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

```text
       k
int k;
k = 5;
```

#### Transkript

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

### Folie 10

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

```text
       5
       k

int k;
k = 5;
```

#### Transkript

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

### Folie 11

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

```text
       5
       k

int k;
k = 5;
int* pk;
```

```text
pk
```

#### Transkript

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

### Folie 12

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

```text
       5                               0x7fff1234
       k

int k;
k = 5;
int* pk;
pk = &k;
```

```text
pk
```

#### 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.2-pointer.pdf#page=13)

```text
       5                               0x7fff1234
       k

int k;
k = 5;
int* pk;
pk = &k;
```

```text
                                        pk
           5
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
0x7fff1234
```

#### Transkript

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

### Folie 14

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

```text
       5                               0x7fff1234
       k

int k;
k = 5;
int* pk;
pk = &k;
```

```text
                                        pk
           5
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
*pk ist 5
```

(pk wird „dereferenziert“)

```text
0x7fff1234
```

#### Transkript

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

### Folie 15

[Folie 15 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=15)

```text
       35                              0x7fff1234
       k

int k;
k = 5;
int* pk;
pk = &k;
*pk = 35; // ändert k (!) auf 35
```

```text
                                        pk
          35
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
*pk ist nun 35
```

```text
0x7fff1234
```

#### Transkript

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

**[Video 03:37–04:14](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=217)**

Die sucht sich der Compiler selber aus.

### Folie 16 — NULL-Pointer

[Folie 16 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=16)

Der einfachste Pointer in C ist der NULL-Pointer (Adresse 0x0).

Er zeigt auf … nichts. Wozu nützlich?

Versucht man, von Adresse 0 zu lesen oder zu schreiben wird das Programm sofort beendet.

Wenn Sie einen Pointer erstellen und nicht sofort initialisieren, sollten Sie ihn auf NULL setzen

Sie können mit dem Gleichheitsoperator (==) prüfen, ob ein Pointer NULL ist.

#### Transkript

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

### Folie 17

[Folie 17 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=17)

Eine Möglichkeit, einen Pointer zu erstellen, ist die Adresse einer bereits existierenden Variable zu extrahieren (`&`).

Wenn `x` eine Variable vom Typ int ist, dann ist `&x` ein Pointer to int, dessen Wert die Adresse von `x` ist.

Pointer müssen nicht so erstellt werden!

Arrays als

Wenn `arr` ein Array von doubles ist, dann ist `&arr[i]` ein Pointer to double, dessen Wert die Adresse des i-ten Elements von `arr` ist.

Pointer

Der Name eines Arrays ist also eigentlich nur ein Pointer auf sein erstes Element.

Sie haben die ganze Zeit schon mit Pointern gearbeitet!

#### Transkript

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

### Folie 18

[Folie 18 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=18)

Eine Möglichkeit, einen Pointer zu erstellen, ist die Adresse einer bereits existierenden Variable zu extrahieren (`&`).

```text
double arr[4] = {1.0, 2.0, 3.0, 4.0};
// arr     ist äquivalent zu &arr[0]
// arr + 1 ist äquivalent zu &arr[1]
// arr + i ist äquivalent zu &arr[i]
```

Wenn `x` eine Variable vom Typ int ist, dann ist `&x` ein Pointer to int, dessen Wert die Adresse von `x` ist.

Pointer müssen nicht so erstellt werden!

Arrays als

Wenn `arr` ein Array von doubles ist, dann ist `&arr[i]` ein Pointer to double, dessen Wert die Adresse des i-ten Elements von `arr` ist.

Pointer

Der Name eines Arrays ist also eigentlich nur ein Pointer auf sein erstes Element.

Sie haben die ganze Zeit schon mit Pointern gearbeitet!

#### Transkript

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

### Folie 19 — Operationen

[Folie 19 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=19)

& ist der Adressoperator, der die Adresse einer Variable liefert. Diese kann man in einem Pointer speichern.

\* ist der Dereferenzierungsoperator; wird auf einen Pointer angewendet. Damit „geht“ man an die Stelle im Speicher und greift auf die Daten dort zu , entweder lesend oder schreibend (bei Zuweisung).

```text
char* pc = &c;
// pc speichert die Adresse von c
char x = *pc;
// x enthält Wert an Adresse pc
*pc = 'A';
// Ändert nur c, nicht x
```

#### Transkript

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

### Folie 20

[Folie 20 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=20)

Eine Möglichkeit, einen Pointer zu erstellen, ist die Adresse einer bereits existierenden Variable zu extrahieren (`&`).

```text
double arr[4] = {1.0, 2.0, 3.0, 4.0};
// arr     ist äquivalent zu &arr[0]
// arr + 1 ist äquivalent zu &arr[1]
// arr + i ist äquivalent zu &arr[i]

arr[i] ist eigentlich *(arr + i)
```

Wenn `x` eine Variable vom Typ int ist, dann ist `&x` ein Pointer to int, dessen Wert die Adresse von `x` ist.

Pointer müssen nicht so erstellt werden!

Arrays als

Wenn `arr` ein Array von doubles ist, dann ist `&arr[i]` ein Pointer to double, dessen Wert die Adresse des i-ten Elements von `arr` ist.

Pointer

Der Name eines Arrays ist also eigentlich nur ein Pointer auf sein erstes Element.

Sie haben die ganze Zeit schon mit Pointern gearbeitet!

#### Transkript

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

### Folie 21 — Vorsicht: Besonderheit der Syntax

[Folie 21 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=21)

```text
int* px, py, pz;  // Was bewirkt dies?
```

Eine weitere Besonderheit bei der Arbeit mit \*: es ist ein Teil des Typnamens aber auch des Variablennamens.

Besser:

```text
int *pa, *pb, *pc;
```

Noch besser:

```text
int* pa;
int* pb;
int* pc;
```

#### Transkript

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

### Folie 22

[Folie 22 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=22)

Datentyp Größe (Byte)

int 4

char 1

float 4

double 8

long long 8

string ???

#### Transkript

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

### Folie 23

[Folie 23 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=23)

Datentyp Größe (Byte)

int 4

char 1

float 4

double 8

long long 8

char\* ???

#### Transkript

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

### Folie 24

[Folie 24 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=24)

Datentyp Größe (Byte)

int 4

char 1

float 4

double 8

long long 8

char\* 4 oder 8

#### Transkript

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

### Folie 25

[Folie 25 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=25)

Datentyp Größe (Byte)

int 4

char 1

float 4

double 8

long long 8

char\*, int\*, … 4 oder 8

#### Transkript

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

### Folie 26

[Folie 26 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=26)

```text
  char *text1   = "Hallo"; //         enthält Adresse 0x7fff1000
  char  text2[] = "Hallo"; // Array, liegt ab Adresse 0x7fff1008

  if (text1 == text2) { // Vergleicht Adressen, nicht Inhalte!
      printf("Gleich");
  }

    H   a   l   l   o  \0          H   a   l   l   o  \0

0x7fff1000
  text1
```

```text
0x7fff1004
```

```text
0x7fff1008
text2
```

```text
0x7fff100c
```

#### Transkript

**[Video 03:37–04:14](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=217)**

Korrekt. Man kann sich solche Adressen übrigens anzeigen lassen und zwar mit printf, wenn man den Formatcode %p nimmt und dann einen Pointer übergibt. Wenn wir uns Adressen anschauen, dann normalerweise in hexadezimaler Form, weil das einfach übersichtlicher ist.

**[Video 04:14–04:32](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=254)**

Ein Vorteil ist auch, dass man am Präfix 0x dann erkennen kann, dass ein bestimmter Wert eine Adresse ist und nicht der Inhalt der Variablen.

### Folie 27 — Pointer versus Arrays

[Folie 27 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=27)

Der Name eines Arrays ist ein Pointer auf sein erstes Element und die Schreibweise `arr[i]` ist äquivalent zu `*(arr` `+ i)`.

```c
int zahlen[4] = {10, 20, 30, 40};
zahlen[2] = 35;
// ist das gleiche wie
*(zahlen + 2) = 35;

void array_func(int arr[]) {
  // arr ist eigentlich ein int*
  // Änderungen wirken sich auf Original aus
}
```

#### Transkript

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

### Folie 28

[Folie 28 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=28)

```c
#include <stdio.h>

void tausche(int *i, int *j)
{
    int temp = *j;
   * j = *i;
   * i = temp;
}

int main(void)
{
    int i = 5, j = 10;
    tausche(&i, &j);
    printf("%i - %i\n", i, j); // gibt 10 - 5 aus
}
```

#### Transkript

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

### Folie 29

[Folie 29 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=29)

```text
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
int k = 5;
int *pk = &k;
*pk = 35;

int m = 4;
pk = &m;
```

#### Transkript

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

### Folie 30

[Folie 30 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=30)

```text
           5
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
int k = 5;
```

#### Transkript

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

### Folie 31

[Folie 31 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=31)

```text
           5
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
0x7fff1234
```

```text
int k = 5;
int *pk = &k;
```

#### Transkript

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

### Folie 32

[Folie 32 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=32)

```text
          35
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
0x7fff1234
```

```text
int k = 5;
int *pk = &k;
*pk = 35;
```

#### Transkript

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

### Folie 33

[Folie 33 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=33)

```text
          35
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
4        0x7fff1234
```

```text
int k = 5;
int *pk = &k;
*pk = 35;

int m = 4;
```

#### Transkript

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

### Folie 34

[Folie 34 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=34)

```text
          35
0x7fff1234        0x7fff1238        0x7fff123c        0x7fff1240
```

```text
4        0x7fff123c
```

```text
int k = 5;
int *pk = &k;
*pk = 35;

int m = 4;
pk = &m;
```

#### Transkript

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

### Folie 35 — Pointer ermöglichen

[Folie 35 als PDF](https://inf.zone/download/lectures/4-memory/4.2-pointer.pdf#page=35)

Ein Pointer ist nichts anderes als eine Adresse

direkten Zugriff auf

Speicherstellen

Mit & erhalten wir die Adresse einer Variable

Arrays und strings sind

intern auch nur Pointer

Mit \* greifen wir auf den Wert an einer Adresse zu

NULL-Pointer schützen

vor undefinierten Speicherzugriffen

> Bildinhalte sind nicht transkribiert; siehe Originalfolie.

#### Transkript

**[Video 04:14–04:32](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=254)**

Statt also von Adresse 0 bis 19 zu sprechen, verwenden wir 0x0 bis 0x13. Dies bringt uns zum wichtigsten Konzept bei Pointern. Ein Pointer ist nichts anderes als eine Adresse.

**[Video 04:32–05:08](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=272)**

Diese eine Tatsache ist der Schlüssel zum Verständnis von Pointern. Das ist wirklich alles. Menschen verwenden doch ständig Adressen, zum Beispiel, wenn sie sich irgendwo verabreden. Dann gibt es noch E-Mail-Adressen, Internet-Adressen. Also eigentlich solltet ihr damit kein Problem haben, dass nun auch Variablen eine Adresse haben. Moment mal, ich sehe schon die fragenden Gesichter im Publikum. Ja, Pointer sind im Kern nur Adressen, aber es gibt da schon noch etwas mehr zu beachten, oder? Aber wieso? Eine Adresse ist eine Adresse. Entweder man weiß, wo etwas ist oder nicht. Ja, aber genau das ist ja das Problem. Pointer schauen grundsätzlich total einfach aus und das sind sie ja irgendwie auch in der Grundidee.

**[Video 05:08–05:42](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=308)**

Aber man kann damit ziemlich komplexe Dinge tun und manchmal verstecken sie sich ja auch im Code und man sieht sie gar nicht. Zum Beispiel bei Arrays. Ja gut, ein paar Details muss man sich schon merken. Aber keine Sorge, wir werden das Schritt für Schritt durchgehen. Genau. Und wenn Sie sich jetzt denken, das ist alles so kompliziert, das ist eigentlich völlig normal. Viele haben an der Stelle schon gestutzt, viele vor Ihnen. Und mit etwas Übung klappt es dann aber auch besser. Man muss sich einfach immer wieder an dieses Mantra erinnern: Pointers sind einfach nur Adressen, an denen irgendwelche Variablen im Speicher stehen. Das hilft, wenn Sie an den Punkt kommen, wo Sie irgendwann mal verwirrt sind.

**[Video 05:42–05:59](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=342)**

Lassen Sie uns jetzt einmal genauer darstellen, was mit Pointern gemeint ist. Wenn wir eine Variable deklarieren, zum Beispiel einen int k, können wir uns das wie eine Box vorstellen. Wenn wir nun einen Pointer auf einen Integer deklarieren, das macht man mit einem Stern, den man hinter den Datentyp schreibt, erstellen wir eine weitere Box.

**[Video 05:59–06:30](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=359)**

Diese Box wird später eine Adresse enthalten, und zwar eine Adresse einer Integer-Variable. Genau wie der Integer k belegt auch der Pointer pk Platz im Speicher. Er steht also irgendwo anders im Speicher und hat erst einmal überhaupt nichts mit k zu tun. Nun kommt ein neuer Operator ins Spiel. Mit dem Adressoperator, dem Kaufmanns-und, können wir die Adresse von k ermitteln und sie pk zuweisen. Moment mal! In unserem Beispiel taucht auf einmal diese Adresse 0x7fff1234 auf. Woher kommt die denn jetzt? Das verwirrt vermutlich einige hier.

**[Video 06:30–07:07](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=390)**

Eine sehr gute Frage. Diese konkrete Adresse ist tatsächlich nur ein Beispiel. Die echte Adresse wird vom Betriebssystem und Compiler zur Laufzeit festgelegt. Als Programmierer müssen wir die genaue Adresse auch gar nicht kennen. Wir verwenden einfach den Adressoperator und er liefert uns die richtige Adresse, wo auch immer die Variable gerade im Speicher liegt. Wenn wir das Programm mehrmals laufen lassen, könnte k jedes Mal an einer anderen Adresse liegen. Was wichtig ist: Der Adressoperator findet k immer, egal wo es liegt, und pk speichert dann diese Adresse. Jetzt denkt man sich vielleicht: Moment, heißt das etwa, dass pk

**[Video 07:07–07:30](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=427)**

Auch eine Adresse hat? Natürlich. Alles, was im Speicher liegt, muss eine Adresse haben. Ein Pointer ist ja auch nur eine Variable. Er speichert zwar Adressen als Werte, aber er selbst muss auch irgendwo im Speicher liegen. Eigentlich doch ganz logisch. Genau wie ein Telefonbuch. Es enthält Adressen, steht aber selbst auch in einem Regal an einer bestimmten Stelle. Oder wie eine Visitenkarte mit einer Adresse drauf. Die Karte selbst muss ja auch irgendwo liegen.

**[Video 07:30–08:02](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=450)**

Damit kommen wir zu einem wichtigen Punkt. In unserem Speicherlayout sehen wir ja, dass pk bei 0x7fff1240 liegt und dort den Wert 0x7fff1234 speichert. Das ist ja die Adresse von k. Das zeigt ziemlich gut den Unterschied zwischen der Adresse des Pointers und der Adresse, die er speichert. Wenn man genau hinschaut, sieht man ja sogar, dass pk im Speicher ziemlich genau sechs Bytes hinter k liegt. [Anm.: 0x7fff1240 − 0x7fff1234 = 0xC, also 12 Byte.] Kommen wir zum wichtigsten Teil: Wie greifen wir auf den Wert zu, auf den ein Pointer zeigt? Dafür verwenden wir den Dereferenzierungsoperator. Das ist der Stern.

**[Video 08:02–08:37](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=482)**

Jetzt denken Sie vielleicht, hä, den Stern haben wir doch schon bei der Deklaration eines Pointers verwendet, oder? Und ja, genau so ist es, aber halt in einem anderen Kontext. Bei Stern pk gehen wir zur Adresse, die in pk gespeichert ist, und holen den Wert, der dort liegt. In unserem Beispiel ist es so: pk enthält die Adresse 0x7f und so weiter. Und an dieser Adresse finden wir den Wert 5. So, was passiert jetzt, wenn wir Stern pk gleich 35 ausführen? Wir folgen der Adresse in pk und ändern den Wert an dieser Stelle im Speicher auf 35. Dadurch ändert sich der Wert von k, da wir ja direkt an der Adresse von k arbeiten.

**[Video 08:37–09:01](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=517)**

Ein besonderer Pointer ist der Null-Pointer. Er ist gewissermaßen ein Pointer, der explizit auf nichts zeigt. Warum sollte ein Pointer, der auf nichts zeigt, für irgendwas nützlich sein? Das ist eine Art Sicherheitsmechanismus. Wenn wir versuchen, einen Null-Pointer zu dereferenzieren, stürzt unser Programm sofort ab. Und das ist besser, als versehentlich irgendwelche undefinierten Speicherstellen zu manipulieren.

**[Video 09:01–09:35](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=541)**

Wir haben bereits den Adressoperator kennengelernt, das Kaufmanns-und. Schauen wir uns an, wo wir ihn überall einsetzen können. Wenn wir eine Integer-Variable x haben, gibt uns und x einen Pointer auf diese Variable. Es gibt aber auch einen Fall, wo man mit Adressen arbeitet, ohne es zu merken, und zwar bei Arrays. Nehmen wir einen Array von Doubles. Wenn Sie mit eckigen Klammern auf das erste Element zugreifen, dann dereferenzieren Sie einen Pointer, ohne es zu merken. Denn der Arrayname ist in C nichts anderes als ein Pointer auf das erste Element. Und wenn Sie davor noch ein Kaufmanns-und schreiben, bekommen Sie die Adresse des Elements. Das erklärt.

**[Video 09:35–10:06](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=575)**

Warum Arrays in Funktionen anders behandelt werden als normale Variablen? Sie werden nicht kopiert, weil sie von Anfang an Pointers sind. Wenn Sie also bisher Arrays verwendet haben, haben Sie unbewusst schon mit Pointern gearbeitet. Arrays und Pointers sind in C eng miteinander verbunden. Lassen Sie uns jetzt noch einmal zusammenfassen, was der Dereferenzierungsoperator Stern macht. Dazu schauen Sie sich am besten folgendes Beispiel in Ruhe an.

**[Video 10:06–10:33](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=606)**

Es ist so ähnlich wie mit der Adresse, an der jemand wohnt. Man kann sich die Adresse auf einen Zettel aufschreiben und wenn man dann etwas mit der Person, die da wohnt, machen will, dann muss man ja da hingehen. Genau. Der Stern-Operator, also das Dereferenzieren, ist das Hingehen. Ohne Stern arbeiten wir nur mit der Adresse. Mit Stern gehen wir im Speicher an die Stelle, die im Pointer gespeichert ist.

**[Video 10:33–11:04](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=633)**

und können den Wert, der dort liegt, lesen oder ändern. Man könnte sich jetzt fragen, wieso wir den Stern beim Zugriff auf Elemente in einem Array nicht benötigen. Der Grund dafür ist, dass das Hingehen fest in der Array-Notation eingebaut ist. Der Compiler holt also die Adresse ausgehend vom ersten Element des Arrays um so viel, wie das Element mit der Nummer i weg ist und dereferenziert dann diese Adresse. Jetzt schauen wir uns noch eine Syntaxbesonderheit bei Pointern an, die häufig für Verwirrung sorgt. Betrachten wir diese Zeile. Was vermuten Sie, was diese Zeile deklariert? Man könnte hier denken

**[Video 11:04–11:42](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=664)**

Dass hier drei Pointer deklariert werden. Tatsächlich wird aber nur px ein Pointer auf einen Integer. py und pz werden normale Integer-Variablen. Obwohl der Stern technisch gesehen zum Datentyp gehört, ist es daher eine gängige Konvention, ihn direkt vor den Variablennamen zu schreiben. Das macht besonders bei Mehrfachdeklarationen den Code klarer. Noch besser ist es aber, für absolute Klarheit jede Deklaration in eine eigene Zeile zu schreiben. Erinnern wir uns an die verschiedenen Datentypen und ihre Größen im Speicher. Ein char braucht ein Byte, ein int vier Bytes und so weiter. Aber was ist mit Strings? Wie viele Bytes braucht ein String?

**[Video 11:42–12:05](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=702)**

Hier kommt eine wichtige Erkenntnis: In C gibt es eigentlich gar keinen eigenen Datentyp String. Was wir als String kennen, ist in Wirklichkeit ein Pointer auf einen char, also ein char Stern. Und wie groß ist ein Pointer? Genau wie jeder andere Pointer auch: vier Bytes auf 32-Bit-Systemen oder acht Bytes auf 64-Bit-Systemen. Moment, 32 Bit, 64 Bit, das musst du kurz erklären.

**[Video 12:05–12:38](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=725)**

Ah ja, das bezieht sich darauf, wie viele Bits ein System für Speicheradressen verwendet. Bei 32 Bits können wir 2 hoch 32 verschiedene Adressen darstellen, also etwa vier Gigabyte Speicher adressieren. Bei 64 Bits sind es 2 hoch 64 Adressen, sehr viel mehr. Moderne Computer sind meist 64-Bit-Systeme. Na super, danke für die Erklärung. Wo waren wir? Wolltest glaube ich noch über Strings sprechen, oder? Ja, nehmen wir den String "Hallo" und schauen uns an, wie er im Speicher abgelegt wird. Dass Strings eigentlich Char-Pointers sind, erklärt übrigens einige seltsame Verhaltensweisen, die Sie vielleicht schon bemerkt haben.

**[Video 12:38–13:16](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=758)**

Zum Beispiel beim Vergleichen von Strings. Deshalb müssen wir für String-Vergleiche strcmp verwenden. Ist gleich Ist gleich vergleicht nur die Adressen, nicht die Inhalte. Auch die Übergabe von Strings an Funktionen ist jetzt klarer. Wir übergeben ja nur den Pointer, nicht den ganzen Text. Das erklärt auch, warum Strings sich bei der Funktionsübergabe anders verhalten, als zum Beispiel Integern. Wir übergeben immer nur die Adresse des ersten Zeichens. Das ist sehr effizient. Aber man muss halt die Implikationen kennen. Sie können in Zukunft also statt unserem Datentyp String, den wir für den einfachen Start verwendet haben, auch die echten char Pointer verwenden. Dann sind Sie schon ohne Stützräder unterwegs.

**[Video 13:16–13:31](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=796)**

Toll, oder? So, jetzt, wo wir gesehen haben, dass Strings einfach nur Char-Pointer sind, ist es vielleicht an der Zeit für eine weitere Erkenntnis: Arrays und Pointer sind in C fast das Gleiche. Schauen Sie sich diese Situation an.

**[Video 13:31–14:07](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=811)**

Der Arrayname zahlen ist eigentlich ein Pointer auf das erste Element. Wenn wir also schreiben zahlen an der Stelle zwei gleich fünfunddreißig, macht der Compiler daraus eine Dereferenzierung des Pointers zahlen plus zwei. Genau, die eckigen Klammern verwenden wir nur deswegen, weil sie einfach übersichtlicher sind. Man sagt manchmal auch, dass sie syntactic sugar sind, also quasi Syntaxzucker, der eigentlich gar nicht nötig wäre, aber den Code halt einfach für uns Menschen besser lesbar macht. Wenn Sie jetzt gut aufgepasst haben, dann sind Sie vielleicht irritiert. Wenn das Array hier Int-Werte enthält

**[Video 14:07–14:38](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=847)**

Und int-Werte ja vier Byte haben, dann ist die Adresse von zahlen an der Stelle zwei, doch gar nicht die Adresse des ersten Elements plus zwei Byte. Das erste Element belegt ja schon vier Byte. Komisch, oder? Stattdessen müssten wir zur Adresse von zahlen plus acht Byte gehen, wenn wir auf das dritte Element zugreifen wollten. Und tatsächlich ist es auch genau das, was passiert, obwohl es gar nicht zu sehen ist. Wenn Sie in C mit einem Pointer, der ja einen bestimmten Datentyp hat, bei uns nämlich int, rechnen, dann berücksichtigt der Compiler bei der Berechnung automatisch

**[Video 14:38–15:02](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=878)**

Den Platzbedarf des Datentyps. Wenn Sie auf einen int-Pointer eine Eins addieren, liefert diese Berechnung eine Adresse, die um vier Byte größer ist. Bei einem Double wäre die Adresse hingegen acht Byte größer. Das nennt man Pointer-Arithmetik. Dass Arrays in C einfach nur Pointers sind, erklärt unser Mysterium von früher. Warum werden Arrays in Funktionen nicht als Wert, sondern als Referenz übergeben? Weil nur der Wert des Pointers übergeben wird, genau wie bei Strings.

**[Video 15:02–15:34](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=902)**

Wenn Sie also in einer Funktion den Wert einer übergebenen Variable ändern können wollen, müssen Sie die Funktion so deklarieren, dass sie einen Pointer für den entsprechenden Datentyp entgegennimmt, so wie das Tauschebeispiel, das ich ganz am Anfang gezeigt habe. Schauen Sie es sich jetzt noch einmal in Ruhe an. Das sollte jetzt mehr Sinn ergeben. Hier. Lassen Sie uns zum Abschluss ein Beispiel durchgehen, das alle Konzepte zusammenbringt. Wir verfolgen Schritt für Schritt, was im Speicher passiert.

**[Video 15:34–16:14](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=934)**

Dieses Beispiel zeigt echt gut, wie Pointer ihre Ziele umschalten können und wie wir sie nutzen können, damit wir Werte verändern können. Ja, und es demonstriert die drei wichtigsten Pointer-Operationen: Adresse erhalten mit dem Kaufmanns-und, Pointer zuweisen und dereferenzieren mit Stern. Normalerweise wäre jetzt der Punkt, wo ich nach den drei extra Minuten fragen würde. Aber ich glaube, das Beispiel hat eigentlich alles schon ganz gut zusammengefasst heute. Oh, wir könnten noch über fortgeschrittenes Speichermanagement sprechen. Und was passiert eigentlich, wenn ein Pointer auf einen anderen Pointer zeigt? Stellen Sie sich vor, ein Pointer, der die Adresse eines Pointers speichert, der wiederum. Nein, nein, nein, hör auf. Ich sehe schon die Panik in den Gesichtern.

**[Video 16:14–16:36](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=974)**

Aber das öffnet so viele Möglichkeiten: mehrfache Indirektion, Pointer-Arrays von Pointern, Pointer auf Funktionen. Und damit beenden wir heute das Video. Denken Sie daran: Ein Pointer ist wie ein Wegweiser. Manchmal zeigt er auf einen Ort, manchmal zeigt er ins Nichts und manchmal zeigt er auf einen anderen Wegweiser. Aber das ist was für eine andere Vorlesung, Mensch. Und rekursive Pointer-Strukturen.

**[Video 16:36–16:49](https://www.youtube.com/watch?v=FN2XlhueoQ0&t=996)**

Haben wir ja auch noch gar nicht behandelt. Bis bald. Dies war Inf-Einf-B.
