Zeiger in C (Zeiger in C), Lektion, Seite 723199
https://www.purl.org/stefan_ram/pub/zeiger_c (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C-Kurs

Zeiger in C 

Bedeutung des Wortes „Zeiger“

Der Begriff „Zeiger“ wird in der C -Norm nicht explizit definiert. In „The C programming language “ von Kernighan und Ritchie findet sich aber die folgende Definition.

The C programming language - Brian Kernighan (1988), Chapter 5
A pointer is a variable that contains the address of a variable.
Aussprachehinweis
Kernighan ˈkɛrnɪhæn (ohne „g“!)

Jedoch wird in jenem Buch der Ausdruck “pointer ” dann doch auch für einen Adreßwert  verwendet, der nicht  in einer Variablen enthalten ist. In Ermangelung einer offiziellen Definition können wir festhalten, daß der Begriff „Zeiger“ praktisch als Synonym zu „Adresse“ gebraucht wird, entweder für einen Adreßwert oder auch für eine Adreßvariable.

Wenn A  die Adresse eines Objektes O  ist, dann sagt man auch, daß A  auf das Objekt O  zeige. Genauso auch, wenn A  eine Variable ist, welche die Adresse eines Objektes O  enthält. Wir nennen das Objekt O  dann auch das Zielobjekt  oder den Referenten  des Zeigers A.

Bei Zeigern kann man auch den Typ des Objektes angeben, dessen Adresse der Zeiger ist oder enthält. Ein Zeiger auf ein Objekt des Typs T  wird also auch als T -Zeiger bezeichnet. In dem obenstehenden Programm ist also »p« ein „int-Zeiger“.

Wenn »p« ein Zeiger auf ein Objekt ist, dann ist »*p« das Objekt, auf das dieser Zeiger zeigt.

Beispielprogramm zu Zeigern

Das folgende Beispielprogramm definiert einen Zeiger »p«, der auf das Objekt »*p« (gleich »i«) zeigt.

main.c

#include <stdio.h>

int main( void )
{ int i = 27;
int * p = &i;
printf( "%d\n", *p ); }

stdout
27

»p« ist der Name eines Objekts, welches die Adresse eines int-Objekts enthalten kann und dann auch enthält. »p« ist der Name eines int-Zeigers (»p« ist ein int-Zeiger).

Bildliche Darstellung von Zeigern

Zeiger werden bildlich dargestellt, indem eine bildliche Darstellung des Zeigers durch einen Pfeil mit einer bildlichen Darstellung seines Zielobjektes verbunden wird. Dabei zeigt jener Pfeil vom Zeiger zu seinem Zielobjekt.

Der int-Zeiger »p« zeigt auf das Objekt »i«
p -------------> i

Änderung des Referenten

In dem folgenden Programm steht »*p« für den Referenten des Zeigers »p«. Daher ändert die Zuweisung »*p = 40;« den Wert von »i«.

main.c

#include <stdio.h>

int main( void )
{ int i = 27;
int * p = &i;
*p = 40;
printf( "%d\n", i ); }

stdout
40

Aliaseffekte

Wir haben schon in dem vorigen Beispiel einen Aliaseffekt kennengelernt: Dort war »*p« nur ein anderer Ausdruck für »i«.

Das folgende Programm zeigt einen weiteren Aliaseffekt. Zwei Zeiger »p« und »q« werden so definiert, daß »*p« dieselbe Bedeutung hat wie »*q«, nämlich »i«. Dann ändert eine Zuweisung an das Objekt »*p« auch das Objekt »*q« beziehungsweise »i«, und beim Lesen aus dem Objekt »*q« wird auch aus dem Objekt »*q« beziehungsweise »i« gelesen (da alle diese Ausdrücke dasselbe Objekt bezeichnen).

Drei identische Ausdrücke
i, *p, *q

In dem folgenden Programm sind »i« und »j« am Anfang zwar gleichwertig, aber nicht gleich, da es zwei verschiedene Variablen sind.

»i«, »*p« und »*q« sind im folgenden Programm aber sogar so weit gleich , daß sie sogar die gleiche Bedeutung haben, wenn sie auf der linken Seite  einer Zuweisung verwendet werden.

main.c

#include <stdio.h>

int main( void )
{ int i = 27;
int j = 27;

int * p = &i;
int * q = &i;

*p = 40; printf( "%d\n", i );
*q = 20; printf( "%d\n", i );

i = 10;
printf( "%d\n", *p );
printf( "%d\n", *q ); }

stdout
40
20
10
10
p und q zeigen auf das gleiche Objekt
p ----------> i <---------- q

Zuweisungen an Zeiger

Der Wert eines Zeigers kann in Laufe der Zeit auch durch Zuweisungen verändert werden. Im folgenden Beispielprogramm zeigt der Zeiger »p« zunächst auf das Objekt »i«, so daß »*p« synonym zu »i« ist, und dann auf das Objekt »k«, so daß dann »*p« synonym zu »k« ist.

main.c

#include <stdio.h>

int main( void )
{ int i = 27;
int k = 40;
int * p = &i; printf( "%d\n", *p );
p = &k; printf( "%d\n", *p ); }

stdout
27
40

Zuweisungen an Zeiger (1)

Wir sehen unten »p = q« – eine Zuweisung von einem Zeiger zu einem anderen Zeiger – und »p = &i« – eine Zuweisung eines Wertes des Adressoperators zu einem Zeiger.

main.c

#include <stdio.h>

int main( void )
{ int i = 27;
int j = 22;
int * p = &i;
int * q = &j;
*p = 40; printf( "%d\n", i );
p = q; *p = 20; printf( "%d\n", j );
p = &i; *p = 10; printf( "%d\n", i ); }

stdout
40
20
10

Der Zeiger »p« zeigt zunächst auf das Objekt »i«, dann auf das Objekt »j« und schließlich wieder auf das Objekt »i«.

Hängende Zeiger

Im folgenden Programm wird eine Adresse eines Objektes abgespeichert und das Objekt dann vernichtet (am Ende der vorletzten Zeile).

Danach darf der Zeiger nicht mehr verwendet werden. Der Zeiger „hängt“, er zeigt nicht mehr auf ein Objekt. Der Zugriff in der letzten Zeile hat also undefiniertes Verhalten.

main.c

#include <stdio.h>

int main( void )
{ int * p;
{ int i = 27; p = &i; }
printf( "%d\n", *p ); }

Der Zeiger »p« zeigt auf das Objekt »i«
p ----------> i

Der Zeiger »p« „hängt“ (oder „baumelt“)
p ----.
;
|
v

In dem folgenden Programm wird eine gültige Adresse an die Funktion »f« übergeben. Die Funktion »f« speichert jene Adresse in einer Variablen mit statischer Lebensdauer. Später verwendet »h« die dann ungültige Adresse wie eine Adresse eines int-Objekts verwendet werden würde, um auf das int-Objekt zuzugreifen, was auch wieder undefiniertes Verhalten  hat.

main.c

#include <stdio.h>

int * g;
void f( int * const p ) { g = p; }
void h( void ) { *g = 0; }

int main( void )
{ { int i = 27; int * p = &i; f( p ); }
h(); }

Man sollte Objektadressen, auf deren Objekte nach dem Aufruf nicht mehr zugegriffen werden soll, also nur an Funktionen übergeben, die auch garantieren, daß die Adressen nach dem Aufruf nicht mehr dereferenziert werden.

Zitat aus C 2011 *
6.2.4 Storage durations of objects
1 An object has a storage duration that determines its lifetime. There are four storage durations: static, thread, automatic, and allocated. Allocated storage is described in 7.22.3.
2 The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
Zitat aus C 2011 *
6.3.2 Other operands
6.3.2.1 Lvalues, arrays, and function designators
1 An lvalue is an expression (with an object type other than void) that potentially designates an object; if an lvalue does not designate an object when it is evaluated, the behavior is undefined.

Übungsfragen

?   Übungsfrage

Sagen Sie die Ausgabe des folgenden Programm voraus, ohne das Programm zu starten!

main.c

#include <stdio.h>
#include <stdlib.h>

int main( void )
{ int x = 10 /* x wird auf 10 gesetzt */;
int y = 2 /* y wird auf 2 gesetzt */;
int * p = &y /* Nun enthaelt p die Adresse von y */;
int z = x/*p /* z erhaelt das Divisionsergebnis */;
printf( "%d\n", z ) /* z wird schließlich ausgegeben */; }

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723199 stefan_ram:723199 Zeiger in C Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723199, slrprddef723199, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/zeiger_c