Für komplexe Programme ist eine Art Indirektion erforderlich (z. B. rekursive oder variabel große Datenstrukturen). Es ist jedoch nicht erforderlich, diese Indirektion über Zeiger zu implementieren.
Die meisten höheren Programmiersprachen (dh nicht Assembly) sind relativ speichersicher und erlauben keinen uneingeschränkten Zeigerzugriff. Die C-Familie ist hier die seltsame.
C ist aus B hervorgegangen, was eine sehr dünne Abstraktion über die Rohmontage war. B hatte einen einzigen Typ: das Wort. Das Wort kann als Ganzzahl oder als Zeiger verwendet werden. Diese beiden sind äquivalent, wenn der gesamte Speicher als einzelnes zusammenhängendes Array betrachtet wird. C behielt diesen ziemlich flexiblen Ansatz bei und unterstützte weiterhin inhärent unsichere Zeigerarithmetik. Das ganze Typensystem von C ist eher ein nachträglicher Gedanke. Diese Flexibilität beim Speicherzugriff machte C für seinen Hauptzweck sehr geeignet: das Prototyping des Unix-Betriebssystems. Natürlich erwiesen sich Unix und C als recht beliebt, so dass C auch in Anwendungen verwendet wird, in denen dieser einfache Ansatz zum Speichern nicht wirklich benötigt wird.
Wenn wir uns die Programmiersprachen vor C ansehen (z. B. Fortran, Algol-Dialekte, einschließlich Pascal, Cobol, Lisp usw.), unterstützen einige von ihnen C-ähnliche Zeiger. Insbesondere wurde das Null-Zeiger-Konzept 1965 für Algol W erfunden. Keine dieser Sprachen versuchte jedoch, eine C-ähnliche, effiziente Sprache für Systeme mit niedriger Abstraktion zu sein: Fortran war für wissenschaftliches Rechnen gedacht, Algol entwickelte einige recht fortgeschrittene Konzepte, Lisp war es Cobol war eher ein Forschungsprojekt als eine Sprache für die Industrie und konzentrierte sich auf Geschäftsanwendungen.
Garbage Collection gab es seit den späten 50er Jahren, also weit vor C (Anfang der 70er Jahre). GC erfordert Speichersicherheit, um ordnungsgemäß zu funktionieren. Sprachen vor und nach C verwendeten GC als normale Funktion. Das macht natürlich eine Sprache viel komplizierter und möglicherweise langsamer, was sich besonders in der Zeit der Mainframes bemerkbar machte. GC-Sprachen waren in der Regel forschungsorientiert (z. B. Lisp, Simula, ML) und / oder erfordern leistungsfähige Workstations (z. B. Smalltalk).
Mit kleineren, leistungsstärkeren Computern im Allgemeinen und mit GC-Sprachen im Besonderen wurde das immer beliebter. Für Nicht-Echtzeit-Anwendungen (und manchmal sogar dann) ist GC jetzt der bevorzugte Ansatz. GC-Algorithmen waren aber auch Gegenstand intensiver Forschung. Als Alternative wurde insbesondere in den letzten drei Jahrzehnten auch eine bessere Speichersicherheit ohne GC weiterentwickelt: Bemerkenswerte Neuerungen sind RAII und Smart Pointer in C ++ sowie Rusts Lifetime System / Borrow Checker.
Java war keine speichersichere Programmiersprache, sondern übernahm im Grunde die Semantik der speichersicheren GCed-Sprache Smalltalk und kombinierte sie mit der Syntax und statischen Typisierung von C ++. Es wurde dann als besseres, einfacheres C / C ++ vermarktet. Aber es ist nur oberflächlich ein C ++ - Nachkomme. Javas Mangel an Zeigern ist viel mehr dem Smalltalk-Objektmodell zu verdanken als der Ablehnung des C ++ - Datenmodells.
Daher sollten „moderne“ Sprachen wie Java, Ruby und C # nicht so interpretiert werden, als würden sie die Probleme von rohen Zeigern wie in C überwinden, sondern als Zeichen vieler Traditionen gesehen werden - einschließlich C, aber auch sichererer Sprachen wie Smalltalk, Simula, oder Lisp.