Zeiger (Pointer) - warum so mächtig?

HD-Driver

Banned
Registriert
Apr. 2021
Beiträge
8
Moin zusammen,

Zeiger. Vor allem in C sind sie ja ein oft genutztes Mittel und stehen auch charakterisierend für die Vorteile von C. Obwohl ich mich jetzt länger damit beschäftige, gibt es immer noch einige Unklarheiten.

Wenn mich z.B. jemand fragt, warum Zeiger denn nun so mächtig sind, kann ich weder eine flüssige, noch eine klare Antwort darauf abgeben.

Also, Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher und man kann mit ihnen viel Chaos anstellen - jemand verglich dies mal mit dem "Zauberstab" aus Harry Potter. Man kann gutes damit bewirken, aber auch viel Unheil anrichten.
Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert sich ja indirekt die Adresse dieser Variablen.
Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise unangetastet lassen sollte.
Stimmt das soweit? Kann man das ergänzen? Das ist doch nicht alles, oder? Weshalb sind Zeiger so ein mächtiger Werkzeug (in C)?

Danke Leute :)
 
HD-Driver schrieb:
Wenn mich z.B. jemand fragt, warum Zeiger denn nun so mächtig sind, kann ich weder eine flüssige, noch eine klare Antwort darauf abgeben.

Weil es eine dumme Frage ist.

HD-Driver schrieb:
Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert sich ja indirekt die Adresse dieser Variablen.
Aufgrund unklarer Verwendungen der Begrifflichkeiten, kann ich diese Frage sowohl mit "Ja", als auch mit "Nein" beantworten.
 
Pointer auf Pointer der Pointer pointet.
 
  • Gefällt mir
Reaktionen: TriggerThumb87
Eine Pointe.

Oder wie ich es ausspreche, weil ich französisch hasse: Po-Ente.
 
Zeiger sind kein mächtiges Werkzeug. Ein Zeiger ist lediglich eine Speicheradresse, also im Prinzip nichts anderes als ein unsigned integer. C bietet im Vergleich zu anderen Programmiersprachen wenig Abstraktionen. Da bei C und C++ wild Zeiger durch die Gegend geworfen werden (z.B. bei Funktionsaufrufen) führt das halt zu den bekannten (Sicherheits)problemen dieser beiden Programmiersprachen: Memory Leaks, Buffer Overflow, use after free, double free, dangling pointer, null pointer dereferencing und was weiss ich noch alles.

Andere Programmiersprachen haben das besser gelöst: Hier gibt es keine Zeiger sondern Referenzen. Und das ist dann keine Speicheradresse mehr sondern ein Verweis auf ein Objekt. Und hier wird dann auch garantiert, dass diese Referenz nicht mehr existiert, wenn das Objekt nicht mehr existiert. Also keine memory leaks, use after free, double free, dangling pointer oder null pointer mehr.
 
  • Gefällt mir
Reaktionen: nco2k, HD-Driver und KitKat::new()
blubberz schrieb:
Andere Programmiersprachen haben das besser gelöst: Hier gibt es keine Zeiger sondern Referenzen. Und das ist dann keine Speicheradresse mehr sondern ein Verweis auf ein Objekt. Und hier wird dann auch garantiert, dass diese Referenz nicht mehr existiert, wenn das Objekt nicht mehr existiert. Also keine memory leaks, use after free, double free, dangling pointer oder null pointer mehr.

Andere Programmiersprachen haben das nicht besser gelöst, sondern sie schränken einfach mehr ein indem sie keine "rohen" Zeiger anbieten. Damit beschränken sie zwar falsche Nutzungen von Zeigern, aber unterbinden auch genauso deren nützlichen features.

Und all die gelisteten Probleme sind, zumindest in C++ (C ist was anderes), keine wirklichen Probleme wenn man einfach die richtigen tools verwendet, z.B.:
-) std::shared_ptr<>, std::weak_ptr und std::unique_ptr<> samt den dazugehörigen deletern für memory management
-) std::reference_wrapper<> für copyable & assignable references
-) &-syntax für plain references
-) Container wie std::string, std:vector<> etc. für array-ähnliche Funktionalität bzw. eben als generelle Container.
-) std::dynamic_cast und andere cast-Konsorten für safe-casts
-) Iteratoren für read/write-traversal von ranges

Das Problem ist also nicht dass es Zeiger gibt, sondern dass zu oft rohe Zeiger eingesetzt werden wenn andere tools angebrachter wären. In modernem C++ finden sich rohe Zeiger zumeist am Level von Bibliothekscode wider und sind dort auch unersetzlich. Auf user-code Ebene sollten sie eher eine Rarität sein.
 
  • Gefällt mir
Reaktionen: BeBur und blubberz
blubberz schrieb:
Andere Programmiersprachen haben das besser gelöst: Hier gibt es keine Zeiger sondern Referenzen. Und das ist dann keine Speicheradresse mehr sondern ein Verweis auf ein Objekt. Und hier wird dann auch garantiert, dass diese Referenz nicht mehr existiert, wenn das Objekt nicht mehr existiert. Also keine memory leaks, use after free, double free, dangling pointer oder null pointer mehr.

Das liegt weniger am Synonym "Referenz", sondern an einer Speicherverwaltung/GC, die den Heap einfach verwaltet.
"Managed" ist auch keine Weiterentwicklung von "Unmanaged", sondern einfach anders.
 
Die Frage ist doch hauptsächlich der Kontext. In welchem Zusammenhang stellt sich die Frage denn?

Natürlich sind Pointer wie in C inzwischen.... sagen wir, überholt. Aber stellen wir uns mal zurück auf die Stufe, es gibt grad erstmal Pointer.

Was sind denn Pointer? Doch eigentlich nur Indirektionen. Ich sage nicht, WAS es ist, sondern WO es steht. Ganz ähnlich dem Mantra was vermutlich jeder von uns schon mal irgendwo gehört hat: ich muß den Fakt nicht kennen, aber ich muß wissen wo ich ihn finde.

Pointer = ich muß einen Haufen Daten nicht mehrfach vorhalten, sondern ich kann auf EINEM Datum arbeiten. Zu Zeiten wo RAM Gold wert war, war das Gold wert.

Kein String ohne Pointer. Kein Array ohne Pointer. Kein Objekt ohne Pointer und damit fällt der gesamte objektorientierte Ansatz ohne Pointer auf die Nase. Keine Pointer, dh. ich kann keinen Bezug herstellen von Datum A nach Datum B; klar kann ich einen Datensatz als Struktur hernehmen und dann sagen, ab Bit X ist dies und ab Bit Y ist jenes; oder ich definiere Trennzeichen -- \0 zum Bleistift -- und separiere damit meine Elemente in der Liste. Oder ich verzichte auf die explizite Separation und terminiere mit der \0 (was mit allen Multibyte-Strings wie CJK oder natürlich Unicode arg problematisch wird).

- Und das ist genau das Problem! Ich habe feste Strukturbreiten! Egal wie ich mir das drehe, irgendwann laufen mir meine Felder in meiner Struktur notwendigerweise über und dann paßt 15 noch rein und 16 gibt einfach ne 0.

Stringoperationen sind ganz besonders interessant. Meine Variable mit dem String drin ist nämlich auch ein Pointer, wo die Adresse auf den ersten Buchstaben drinsteht. Will ich einen Teilstring, nehm ich einfach Pointerbreite mal Anzahl Zeichen, addiere die auf den Pointer und hab den Anfang meines neuen Teilstrings schon gefunden. Dasselbe gilt aber auch für alles andere, und während es natürlich heutzutage weder empfehlenswert noch groß möglich ist, so war es damals(tm) mit Pointern ein Leichtes, sich selber während der Laufzeit zu ändern.


Also ja. Ich würde schon sagen, daß Pointer sehr mächtig sind.
 
  • Gefällt mir
Reaktionen: areiland
Zurück
Oben