www.wikidata.de-de.nina.az
Der Zeiger oder der Pointer in der Programmiersprache C ist eine Variable in der eine Speicheradresse gespeichert wird Solche Zeiger werden in C haufig eingesetzt Inhaltsverzeichnis 1 Definition 2 Zuweisungen 2 1 Adressoperator 2 2 Inhaltsoperator 2 3 Nullzeiger 3 Zeigerarithmetik 3 1 Zeiger erhohen und vermindern 3 2 Vergleiche von Zeigern 3 3 Differenz von Zeigern 4 Zeiger und Felder 5 Zeiger auf Zeiger 6 Zeiger auf Zeichenketten 7 Anwendungsgebiete 7 1 Verwaltung von dynamischem Speicher 7 2 Zeiger als Funktionsparameter 7 3 Zeiger als Ruckgabewert einer Funktion 7 4 Datenstrukturen 7 5 Rekursive Datenstrukturen 7 6 Verarbeitung von Datenobjekten beliebigen Typs 8 Speichergrosse von Zeigern 9 Typensicherung 10 Literatur 11 EinzelnachweiseDefinition BearbeitenDie Definition eines Zeigers besteht aus dem Datentyp des Zeigers und dem gewunschten Zeigernamen Der Datentyp eines Zeigers besteht wiederum aus dem Datentyp des Wertes auf den gezeigt wird sowie aus einem Asterisk Ein Datentyp eines Zeigers ware also z B double int zeiger1 kann eine Adresse aufnehmen die auf einen Wert vom Typ Integer zeigt int zeiger2 das Leerzeichen kann sich vor oder nach dem Stern befinden int zeiger3 ebenfalls moglich int zeiger4 zeiger5 Definition von zwei Zeigern int zeiger6 ganzzahl Definition eines Zeigers und einer Variablen vom Typ Integer Ein definierter Zeiger der noch nicht initialisiert wurde zeigt auf eine zufallige Adresse Bei einem Zugriff auf diese Adresse kann es zu einem Programmabsturz oder zum Uberschreiben des an dieser Adresse gespeicherten Wertes kommen Zeiger sollten also immer initialisiert werden Zuweisungen BearbeitenDie Zuweisung einer Adresse an einen Zeiger erfolgt mithilfe des Adressoperators eines Feldes eines weiteren Zeigers oder des Wertes von NULL int variable 0 int feld 10 int zeiger int zeiger2 zeiger amp variable mit Adressoperator zeiger feld mit Feld zeiger zeiger2 mit weiterem Zeiger zeiger NULL mit NULL Adressoperator Bearbeiten Die Adresse einer Variablen kann vom Programmierer zwar nicht bestimmt aber uber den unaren Adressoperator amp ermittelt werden Die Adresse eines Datenobjektes ist uber die gesamte Laufzeit des Programms unveranderlich Der Adressoperator kann auf alle Datenobjekte mit Ausnahme von Bitfeldern und Datenobjekten der Speicherklasse register angewendet werden 1 int variable 0 Definition einer Variable vom Typ int und Initialisierung int zeiger amp variable Definition einer Zeigervariablen und Initialisierung printf p void amp variable gibt Adresse der Variablen in einer implementierungsabhangigen Darstellung aus z B als Hexadezimalzahl Inhaltsoperator Bearbeiten Hat man eine Adresse zur Verfugung kann man mithilfe des Inhaltsoperators auf den Wert der an dieser Adresse gespeichert ist zugreifen Der Stern in der Definition eines Zeigers ist nicht der Inhaltsoperator es wird also dasselbe Symbol fur unterschiedliche Zwecke verwendet Bei der Verwendung des Inhaltsoperators auf einen Zeiger spricht man auch von der Dereferenzierung des Zeigers int variable 3 int zeiger amp variable hier handelt es sich nicht um den Inhaltsoperator printf d amp variable gibt den Wert 3 aus printf d zeiger gibt den Wert 3 aus zeiger 5 printf d zeiger gibt den Wert 5 aus zeiger zeiger 1 printf d zeiger gibt den Wert 6 aus Nullzeiger Bearbeiten Soll ein Zeiger auf kein Objekt zeigen kann man ihm den Wert NULL zuweisen Der Zeiger ist damit ungultig und kann solange ihm keine gultige Adresse zugewiesen wird auch nicht sinnvoll genutzt werden eine Dereferenzierung fuhrt meistens zu einem Laufzeitfehler nebst Programmabbruch Sinnvoll hingegen ist der Vergleich von Daten Objektzeigern mit NULL was auch die Hauptanwendung ist int zeiger zeiger NULL zeiger 0 Fehler zeiger malloc sizeof zeiger if zeiger NULL puts Fehler bei Speicherreservierung NULL ist ein Macro und wird in mehreren Header Dateien definiert mindestens in stddef h Die Definition ist vom Standard implementierungsabhangig vorgegeben und vom Compilerhersteller passend implementiert z B define NULL 0 define NULL 0L define NULL void 0Zeigerarithmetik BearbeitenZeiger erhohen und vermindern Bearbeiten Zeiger konnen nur mithilfe der Rechenoperationen Addition einer Ganzzahl und Subtraktion einer Ganzzahl verandert werden Bei der Addition einer Ganzzahl wird die vom Zeiger gespeicherte Adresse entsprechend erhoht bei der Subtraktion vermindert char zeichen char zeiger amp zeichen printf p n zeiger gibt z B die Adresse 0019FF01 aus zeiger zeiger 1 printf p n zeiger gibt dann die Adresse 0019FF02 aus Die Summe einer in einem Zeiger gespeicherten Adresse und einer Ganzzahl ergibt in C allerdings nur bei einem Zeiger auf einen Character die um die Ganzzahl erhohte Adresse Vor der Addition wird die Ganzzahl namlich noch mit der Speichergrosse des Datentyps multipliziert auf den der Zeiger verweist Wenn ein Integer vier Bytes benotigt ergibt die Addition einer Adresse die auf einen Integer zeigt mit der Ganzzahl Eins die um vier Ganzzahlen hohere Adresse Mit der Addition und Subtraktion auf Zeigern kann also bequem um ein oder mehr Werte nach vorn bzw hinten gesprungen werden int zahl int zeiger amp zahl printf p n zeiger gibt z B die Adresse 0019FF01 aus zeiger zeiger 2 printf p n zeiger gibt dann 0019FF09 aus also 0019FF01 plus 4 mal 2 Addition und Subtraktion konnen wie in C allgemein ublich auch hier verkurzt angeschrieben werden zeiger 5 zeiger Vergleiche von Zeigern Bearbeiten Um Zeiger zu vergleichen konnen die Vergleichsoperationen lt gt lt gt und verwendet werden Die Grosser Kleiner Vergleiche sind jedoch nur fur Elemente des gleichen Arrays definiert Fur verschiedene Objekte die nicht Elemente des gleichen Arrays sind ist das Ergebnis undefined behavior Differenz von Zeigern Bearbeiten Um zu ermitteln wie viele Elemente zwei Zeiger auseinanderliegen steht der in der Header Datei stddef h definierte primitive Datentyp ptrdiff t zur Verfugung Er wird verwendet um das Ergebnis einer Subtraktion von zwei Zeigern zu speichern deren Ergebnis gleichbedeutend mit der Entfernung der beiden Zeiger ist int array 10 20 30 40 int zeiger amp array int zeiger2 array 2 ptrdiff t differenz zeiger2 zeiger printf d n differenz gibt die Entfernung der Elemente an hier 2 Auch diese Operation ist nur fur Elemente des gleichen Arrays definiert Zeiger und Felder BearbeitenZeiger und Felder konnen vom Programmierer in vielen Fallen mit genau derselben Syntax verwendet werden jedoch nicht in allen int zeiger int feld 1 2 3 zeiger feld Zugriff auf die in einem Zeiger bzw einem Feld gespeicherte Adresse printf p n zeiger gibt beispielsweise 0019FEEC aus printf p n feld gibt dann ebenfalls 0019FEEC aus Zugriff auf die Adresse eines Elements eines Feldes printf p n amp zeiger 1 gibt dann ebenfalls 0019FEF0 aus printf p n amp feld 1 gibt dann ebenfalls 0019FEF0 aus printf p n zeiger 1 gibt dann ebenfalls 0019FEF0 aus printf p n feld 1 gibt dann ebenfalls 0019FEF0 aus Zugriff auf den Wert eines Elements eines Feldes printf d n zeiger 1 gibt 2 aus printf d n feld 1 gibt 2 aus printf d n zeiger 1 gibt 2 aus printf d n feld 1 gibt 2 aus Das Arbeiten mit Zeigern unterscheidet sich vom Arbeiten mit Feldern insofern als die Adresse eines Feldes konstant und deshalb nicht veranderbar ist int zeiger int feld 3 zeiger feld feld zeiger ergabe hingegen einen Fehler zeiger feld ergabe hingegen einen Fehler auch hat der Zeiger selbst eine andere Adresse als das Feld printf p p n amp zeiger zeiger ergibt beispielsweise 0019FEF8 0019FEE4 printf p p n amp feld feld ergibt dann 0019FEE4 0019FEE4 Wird ein Feld an eine Funktion ubergeben so wird es unabhangig von der Funktionsdeklaration immer in einen Zeiger auf sein erstes Element umgewandelt void funktion int feld void funktion int feld gleichbedeutend wie obige Deklaration Zeiger auf Zeiger BearbeitenEin Zeiger kann auf Objekte von beliebigem Datentyp zeigen also auch auf Zeiger selbst Dies lasst sich endlos fortsetzen mit Zeigern die auf Zeiger zeigen die auf Zeiger zeigen usw In der Praxis kommen Zeiger auf Zeiger durchaus vor bereits sehr selten auch noch Zeiger auf Zeiger die auf Zeiger zeigen int zahl 3 int zeiger amp zahl Zeiger auf Objekt vom Typ Integer int zeiger2 amp zeiger Zeiger auf Zeiger auf Objekt vom Typ Integer Zeiger auf Zeichenketten BearbeitenEine Zeichenkette ist immer ein Feld dessen Feldelemente Zeichen sind Mit einem Zeiger kann man auf den Anfang einer Zeichenkette zeigen Zeiger auf Zeichenketten werden haufig genutzt beispielsweise bei der Ubergabe von Zeichenketten an Funktionen char feld Hallo char zeiger Welt zeiger zeigt auf ein anonymes Array feld 3 Z das Ergebnis von zeiger 3 Z ist im Standard hingegen nicht definiert zeiger feld feld zeiger ist hingegen nicht moglich printf s zu n feld sizeof feld gibt z B HalZo 6 aus printf s zu n zeiger sizeof zeiger gibt z B HalZo 4 aus Anwendungsgebiete BearbeitenVerwaltung von dynamischem Speicher Bearbeiten Dynamischer Speicher findet in C im Gegensatz zu automatischem oder statischem Speicher Verwendung in Situationen in denen erst zur Laufzeit die erforderliche Grosse bekannt ist oder die gewunschte Grosse die Grenzen des automatischen statischen Speichers im Prozess uberschreitet Um wahrend der Laufzeit dynamischen Speicher fur das Programm anzufordern muss in C die Funktion malloc oder die zu ihr ahnliche Funktionen calloc realloc verwendet werden malloc reserviert den benotigten Speicher und liefert einen Zeiger auf diesen zuruck Ebenso muss in C die Freigabe dieses Speichers nach Gebrauch manuell mit der Funktion free erfolgen Um in C mit dynamischem Speicher zu arbeiten ist es also unumganglich auch mit Zeigern zu arbeiten int zeiger malloc sizeof int Zeiger auf den Beginn eines zur Laufzeit reservierten Speicherbereiches hier Speicher fur genau einen int Wert Verwendung von zeiger zeiger 0 1 printf d zeiger 0 zeiger 2 printf d zeiger free zeiger Freigeben des Speichers nach free bedeutet die Verwendung von zeiger undefiniertes Verhalten UB Beim Freigeben von dynamischem Speicher mit free ist darauf zu achten dass der Zeigerwert d h die gespeicherte Adresse exakt die gleiche ist wie zum Zeitpunkt von malloc und dass free nur genau einmal mit dieser Adresse aufgerufen wird int zeiger malloc 10 sizeof int Verwendung von zeiger for int i 0 i lt 10 i zeiger i i for int i 0 i lt 10 i printf d zeiger i free zeiger Freigeben des Speichers free zeiger Fehler int zeiger malloc 10 sizeof int zeiger free zeiger Fehler Zeiger als Funktionsparameter Bearbeiten Fur Funktionsparameter die nicht als Zeiger ubergeben werden call by value wird innerhalb der Funktion eine Kopie erzeugt Ist eine Kopie nicht notig oder unerwunscht ist es auch moglich Zeiger auf Datenobjekte an Funktionen zu ubergeben call by reference Ein weiterer wichtiger Grund fur die Ubergabe von Zeigern an Funktionen ist der eingeschrankte Gultigkeitsbereich von Variablen Es ist nur dann moglich innerhalb von Funktionen Variablen aufrufender Programmblocke zu verandern wenn diese entweder global sind was meist unerwunscht ist oder der Funktion Zeiger auf diese Variablen ubergeben werden void funktion int zeiger zeiger 1 der Wert an der ubergebenen Adresse wird mit 1 uberschrieben main int ganzzahl 0 funktion amp ganzzahl als Argument wird eine Adresse ubergeben printf d n ganzzahl gibt 1 aus Die Parameterubergabe mithilfe von Zeigern ist auch die einzige Moglichkeit um auch Funktionen als Argumente an andere Funktionen ubergeben zu konnen Zeiger als Ruckgabewert einer Funktion Bearbeiten Viele Funktionen der Standard Bibliothek geben einen Zeiger als Ruckgabewert zuruck Der zuruckgegebene Zeiger ist dabei immer ein Zeiger auf die Anfangsadresse des Ruckgabetyps Anwendung findet diese Methode in C vor allem zur Ubergabe von Zeichenketten und Strukturen int funktion void static int zahl 3 int zeiger amp zahl return zeiger hier wird ein Zeiger zuruckgegeben main int zeiger zeiger funktion printf d n zeiger gibt 3 aus Datenstrukturen Bearbeiten Siehe den Artikel Verbund Datentyp Rekursive Datenstrukturen Bearbeiten Rekursive Datenstrukturen wie Listen oder Baume sind kaum ohne Zeiger implementierbar Verarbeitung von Datenobjekten beliebigen Typs Bearbeiten Mithilfe des typenlosen void Zeigers lassen sich Datenobjekte beliebigen Typs verarbeiten Speichergrosse von Zeigern BearbeitenDie Speichergrosse die ein Zeiger benotigt hangt von der Implementierung ab und betragt in der Regel zwischen zwei und acht Bytes Ermittelt wird die Grosse mit der Funktion sizeof Da ein Zeiger immer nur eine Adresse speichert ist es unerheblich ob der Zeiger beispielsweise auf eine Integer oder eine Double Variable zeigt int zeiger double zeiger2 printf zu n sizeof zeiger gibt zum Beispiel 4 aus printf zu n sizeof zeiger2 ergibt denselben Wert noch einmal hier also wieder 4 Typensicherung BearbeitenDer Datentyp Zeiger ist in C streng typisiert So ist beispielsweise die Zuweisung einer Adresse einer Double Variablen an einen Zeiger vom Datentyp int zulassig fuhrt in der Regel jedoch nicht zu sinnvollen Ergebnissen Daher sind Zeigervariablen in C nicht typsicher und nur im Sinne der Speicheradresse zuweisungskompatibel nicht jedoch in Bezug auf die referenzierten Datentypen Somit kann es bei der Programmierung leicht zu Typverletzungen kommen die wiederum instabile oder fehlerhafte Programme verursachen konnen 2 Literatur BearbeitenBrian Kernighan Dennis Ritchie The C Programming Language 2 Auflage Prentice Hall Englewood Cliffs NJ 1988 ISBN 0 13 110362 8 S 93 126 Deutsche Ubersetzung Brian Kernighan Dennis Ritchie Programmieren in C Mit dem C Reference Manual in deutscher Sprache 2 Auflage Hanser Munchen Wien 1990 ISBN 3 446 15497 3 Einzelnachweise Bearbeiten Brian Kernighan Dennis Ritchie The C Programming Language 2 Auflage Prentice Hall Englewood Cliffs NJ 1988 ISBN 0 13 110362 8 S 94 CSE 341 Unsafe languages C Computer Science washington edu abgerufen am 2 Dezember 2016 Abgerufen von https de wikipedia org w index php title Zeiger C amp oldid 237625597