Twitter und Facebook-Anbindung
X
Tweet Follow @twitterapi
!!! Anbindung an twitter und facebook öffnen !!!

Wenn Ihnen mein Online-Buch gefällt,
dann bedanken Sie sich doch mit einer kleinen Spende...

9.1 Einführung in Zeiger

9.1 Einführung in Zeiger

Wie der Name schon verrät, handelt es sich bei Zeigern nicht im klassischen Sinne um Variablen die Werte beinhalten, sondern um Verweise, die auf Speicherbereiche zeigen, an welchen Werte stehen (ähnlich einer Verknüpfung bei auf eine Datei). Natürlich haben Zeiger oder auch Pointer genannt, auch Werte, da sie erst einmal ganz normale Variablen sind. Jene Werte repräsentieren aber nur eine Adresse im Speicher, an welcher man einen Wert eines bestimmten Typs findet. Der Verweis kann, muss aber nicht, auf eine Variable zeigen.

Gerade Neulinge tun sich schwer mit Pointern oder haben auch in gewisser Weise Angst vor ihnen. Ich möchte versuchen diese Einstellung zu ändern, denn Pointer sind das wichtigste bei der Programmierung und intern wird fast ausschließlich mit ihnen gearbeitet. Wann immer der Prozessor Daten benötigt, benutzt er eine Speicheradresse, welche dann an die entsprechenden Steuerwerke geschickt werden. Jene holen dann genau die Daten aus dem Arbeitsspeicher, welche an der gewünschten Adresse stehen. Auch der Stack benötigt einen s.g. Stackpointer, welcher auf die nächste freie Stelle zeigt. Wenn eine Funktion aufgerufen wird, steht im Bytecode auch nur eine Speicheradresse, an welche gesprungen werden soll.

Wenn Sie einen Brief schreiben, dann schreiben Sie auf den Briefumschlag auch eine Adresse, damit die Post weiß, wohin der Brief geschickt werden soll. Wenn Sie jemanden anrufen, dann benutzen Sie auch eine Art Adresse, nämlich die Telefonnummer. Selbst beim Surfen im Internet benutzen Sie Adressen. Sie sehen also, dass das Prinzip einer Adressierung für Sie nicht neu sein dürfte. Der Umgang mit Adressen beim Programmieren ist zwar zu Beginn gewöhnungsbedürftig, aber erlernbar.

Zeiger verweist auf Variable

Hier sehen Sie, dass die Zeigervariable "pZeiger", welche sich selbst bei Adresse "0xFFFF4824" befindet, auf die Variable "iWert" verweist. Deshalb entspricht auch der Wert von "pZeiger" der Speicheradresse von "iWert", also "0xFFFF4828". Stellen Sie sich einfach vor, "pZeiger" wäre ihr Telefon und die Speicheradresse die Telefonnummer ihres Telefons, also "FFFF4828". Jetzt wollen Sie "iWert" anrufen. Sie geben also die Speicheradresse bzw. die Telefonnummer von "iWert" an. Nach dem wählen besteht eine Verbindung zwischen Ihrem Telefon und des anderen. Wenn man über Ihr Telefon fragt, wie alt bist du, kann der andere beispielsweise "15" antworten. Man bekommt also über Ihr Telefon heraus, wie alt der andere ist und so kann man auch über einen Pointer den Wert einer anderen Variable in Erfahrung bringen.

Das Schema sieht so aus: <Variablentyp> *<Zeigername> [= <KonstanterAusdruck>]

Wenn man einen Zeiger mit "nichts" initialisieren will, dann weist man ihm den Wert "NULL" zu (ähnlich eines Telefons, was noch nicht angemeldet wurde). Diesen Wert sollten Sie Zeigern immer zuweisen, wenn sie momentan nicht gebraucht werden. So kann man besser prüfen, ob der Zeiger auf etwas Sinnvolles zeigt oder nicht. Der Wert "0" hingegen, repräsentiert eine gültige Speicheradresse und ist somit nicht geeignet für nicht benutzte Pointer.

Zum Seitenanfang
Zum Inhaltsverzeichnis

9.1.3 Einfache Beispiele an Bildern erklärt

9.1.3 Einfache Beispiele an Bildern erklärt

Die Figuren "iThomas" und "iTobias" sind normale Variablen und dadurch gekennzeichnet, dass sie ihren Wert in der Hand halten. "pNils" hingegen ist ein Zeiger und dadurch kenntlich gemacht, dass er nichts in der Hand hält, sondern auf etwas zeigt.

 1
 2
 3
					
int iThomas;
int *pNils	= NULL;
int iTobias	= 18;
					

Initialisierung der Variablen und des Zeigers

Hier wurden zunächst zwei normale Integervariablen "iThomas" und "iTobias" definiert, wobei "iTobias" auch gleich einen Wert bekommt. Der Wert von "iThomas" ist erst einmal undefiniert. In Zeile 2, wird jetzt ein Zeiger namens "pNils" erzeugt, welcher zunächst auf nichts zeigt, also "NULL". Die Blöcke neben jeder Figur, sollen ihre Speicheradressen repräsentieren.

 1
					
pNils = &iTobias;
					

Zeiger verweist jetzt auf eine Variable

Hier wurde dem Zeiger "pNils" die Adresse von "iTobias" zugewiesen. "pNils" zeigt von nun an auf "iTobias" und hat also als Wert die Speicheradresse von "iTobias".

 1
					
iThomas = *pNils;
					

Variable bekommt Wert durch Dereferenzierung eines Zeigers

Jetzt möchte "iThomas" gerne den Wert haben, auf welchen "pNils" zeigt. "pNils" fragt jetzt quasi "iTobias" "Was hast du für einen Wert "iTobias"?", worauf "iTobias" ihm ins Ohr flüstert: "18!". Diese Information gibt "pNils" nun an "iThomas" weiter und der neue Wert von "iThomas" ist 18.

 1
					
iThomas = (int)pNils;
					

Vektor aus Pointer Kopieren

Weil "iThomas" neugierig ist, wohin "pNils" zeigt, bzw. sich "iTobias" im Speicher aufhält, fragt er "pNils" "Sag mal, worauf zeigst du eigentlich die ganze Zeit?", worauf ihm "pNils" antwortet: "Na dahin wo "iTobias" im Speicher steht!". Also bekommt "iThomas" als Wert den Vektor von "pNils" und somit die Adresse von "iTobias".

ACHTUNG! "iThomas" ist jetzt kein Zeiger, auch wenn man ihn mit einem "*" benutzten würde (evtl. weißt der Compiler diese Zuweisung sogar ab, da die formalen Typen nicht übereinstimmen). Er hat die Adresse zwar als Wert gespeichert, aber man kann/darf trotzdem keine Dereferenzierung durchführen. Allerdings könnte der Wert von "iThomas" einem neuen Zeiger zugewiesen werden, welcher dann auch auf "iTobias" zeigen würde. Jener Wert könnte z.B. "pJakob" zugewiesen werden und somit würde er auch auf "iTobias" zeigen.

 1
					
*pNils = 7;
					

Wertzuweisung einer Variable über Dereferenzierung eines Zeigers

Hier sagt das Programm "pNils": "Ey du, gib mal deinem Kollegen den Wert 7!", worauf "pNils" folgendes in das Ohr von "iTobias" flüstert: "Nur damit du Bescheid weißt, wenn man dich fragt, dann antworte von jetzt an immer mit 7!".

Zum Seitenanfang
Zum Inhaltsverzeichnis

9.1.2 Der & Operator

9.1.2 Der & Operator

Diesen Operator hatte ich bereits kurz angesprochen. Immer wenn vor einer Variable ein "&" Operator steht, wird nicht der Wert der Variable betrachtet, sondern die Adresse der Variable im Speicher. Dies kommt oft vor, wenn man Pointer initialisiert bzw. einen Pointer auf eine Variable verweisen lassen will und wenn man Variablen (nicht ihren Wert) einer Funktion übergeben möchte, welche sie manipulieren soll (alternative zu call-by-reference, wie dies bereits bei der Funktion "scanf" angerissen wurde). Wie dies funktionieren könnte, sehen Sie auch in Kapitel 9.2.

Zum Seitenanfang
Zum Inhaltsverzeichnis

9.1.1 Der * Operator

9.1.1 Der * Operator

Immer wenn vor einer Variable ein * steht, dann wird ihr Wert als Adresse angesehen und somit dereferenziert. In Folge wird nun im Hintergrund zu dieser verwiesenen Adresse gesprungen und die gewünschte Aktion (Auslesen oder Beschreiben) durchgeführt (entspricht dem Doppelklick auf eine Windows-Verknüpfung - nicht die Verknüpfung wird geöffnet, sondern die Datei, auf welche verwiesen wird).

An dieser Stelle seine schon erwähnt, dass dieser Operator eine schwache Bindung hat, was ich in Kapitel 9.2 an einem Beispiel demonstrieren werde.

Zum Seitenanfang
Zum Inhaltsverzeichnis

© Copyright by Thomas Weiß, 2009 - 2012