Skip to content

Pointer

starlightViewModes.switchTo

This content is not available in your language yet.

Pointer sind Variablen, welche Speicheradressen aufnehmen und somit zu anderen Daten zeigen. Pointer bieten ein umfangsreiches und mächtiges Tool, um mit Datentypen zu interagieren, welche mehr als ein Byte Speicherplatz benötigen. Vor allem für den Umgang mit Arrays sind Pointer in C überaus wichtig.

Wie man im nachfolgenden Code sehen kann, gibt es die beiden Operatoren * und & in Bezug auf Pointer.

// Variable i mit Wert 12
int i = 12;
// Pointer-Variable p
int *p = NULL;
// Pointer auf val
p = &i;
// Ausgabe von p (Adresse)
printf("Adresse: %p", p); // zB: Adresse: 0x00000008
// Ausgabe von p (Wert)
printf("Wert: %d", *p); // Wert: 12

Der finale Zustand des Programms im Arbeitsspeicher (Stack) ist hier visualisiert (die Adressen sind natürlich frei erfunden und dies ist nur ein fiktiver Auszug aus dem Arbeitsspeicher):

VariablennameAdresseWert
i0000000812
p0000006900000008

Operatoren

Die Funktionalitäten von * und & werden in dieser Tabelle dargestellt:

SymbolFunktionBeispiel
*

Pointer erstellen

Anmerkung

: Die Position des Sternchens relativ zum Variablennamen macht keinen Unterschied. Jedoch gilt das Sternchen immer nur für die folgende Variable! In Beispiel 4 wird demnach genau wie in Beispiel 3 nur ein Pointer und eine normale Variable erstellt.

int *p;
int* p;
int *p, q;
int* p, q;
den Wert des Pointers auslesen (Dereferenzierung)int i = *p;
&

Mit dem Adressoperator kann man einen Wert zu einem Pointer konvertieren (die Adresse des Wertes auslesen).

int *p = &i;

mit Arrays arbeiten

Häufig müssen wir mit Arrays, sprich Listen von Werte, arbeiten. Arrays werden in C mittels Pointern realisiert, da es in C keine Referenzen, sondern nur Pointer gibt. Das bedeutet, dass beim Deklarieren ein Pointer auf das erste Element zeigt und die Daten im Stack gespeichert werden. Aus diesem Grund ist es auch nicht möglich, außerhalb des Scopes die Größe eines Arrays herauszufinden. Hierbei soll vorab angemerkt werden, dass beim Deklarieren des Pointers automatisch die Liste referenziert wird. Somit machen diese Code-Beispiele das gleiche:

uint8_t numbers[] = { 1, 2, 3, 4, 5 };
uint8_t *p = &numbers;
uint8_t numbers[] = { 1, 2, 3, 4, 5 };
uint8_t *p = numbers; // Automatische Dereferenzierung

Beide Pointer in dem obigen Beispiel zeigen somit auf das erste Element des Arrays. Somit sieht ein Teil des Arbeitsspeichers (Stack) folgendermaßen aus (Adressen frei erfunden).

VariablennameAdresseWert
numbers00000F0000000F01
00000F011
00000F022
00000F033
00000F044
00000F055
p00000F4200000F01

Nun kann man auf die einzelnen Werte des Arrays zugreifen, indem man entweder den []-Operator nutzt oder den Index und den Pointer addiert und anschließend dereferenziert.

// []-Operator
uint8_t three = numbers[2];
// Pointer Zugriff
three = *(numbers + 2);

Wenn man alle Elemente dieses Arrays nun ausgeben will, kann der C-Code von unten verwendet werden. Die Methode sizeof ist hierbei nur in diesem Scope verfügbar, da hier auch die Varibale numbers deklariert ist.

uint8_t numbers[5] = { 1, 2, 3, 4, 5 };
for(int i = 0; i < sizeof(numbers); i++) {
printf("%u", *(numbers + i));
}

Bei Strings, sprich Array von Zeichen, wird beim Erstellen automatisch ein Terminierungssymbol (\0) nach dem Array gespeichert, sodass man untige while-Schleife zum Ausgeben verwenden kann. Die while-Schleife hört automatisch am Ende der Zeichenkette auf, da das Terminierungszeichen \0 einer falschen Bedingung entspricht. Genau auf diese Art und Weise werden beim USART die Zeichen einzeln hintereinander versendet.

char buffer[10] = "Hallo";
char *p = buffer;
while(*p) {
printf("%c", *p);
p++;
}

Wohlgemerkt kann man das Dereferenzieren und Addieren des Pointers gleich in einer Zeile schreiben.

char buffer[10] = "Hallo";
char *p = buffer;
while(*p) {
printf("%c", *p++);
}