Une sorte d'indirection est nécessaire pour les programmes complexes (par exemple, les structures de données récursives ou de taille variable). Cependant, il n'est pas nécessaire d'implémenter cette indirection via des pointeurs.
La majorité des langages de programmation de haut niveau (c'est-à-dire pas Assembly) sont assez sûrs pour la mémoire et interdisent l'accès illimité au pointeur. La famille C est étrange ici.
C a évolué à partir de B qui était une abstraction très mince par rapport à l'assemblage brut. B avait un seul type: le mot. Le mot peut être utilisé comme entier ou comme pointeur. Ces deux sont équivalents lorsque toute la mémoire est considérée comme un seul tableau contigu. C a conservé cette approche plutôt flexible et a continué à prendre en charge l'arithmétique des pointeurs intrinsèquement dangereux. Le système de type entier de C est plus une réflexion après coup. Cette flexibilité d'accès à la mémoire a rendu C très approprié pour son objectif principal: le prototypage du système d'exploitation Unix. Bien sûr, Unix et C se sont avérés très populaires, de sorte que C est également utilisé dans des applications où cette approche de bas niveau de la mémoire n'est pas vraiment nécessaire.
Si nous regardons les langages de programmation qui ont précédé le C (par exemple les dialectes Fortran, Algol, y compris Pascal, Cobol, Lisp,…), certains d'entre eux prennent en charge les pointeurs de type C. Notamment, le concept de pointeur nul a été inventé pour Algol W en 1965. Mais aucun de ces langages n'a essayé d'être un langage de systèmes efficaces et à faible abstraction de type C: Fortran était destiné au calcul scientifique, Algol a développé des concepts assez avancés, Lisp était plus d'un projet de recherche que d'un langage de qualité industrielle, et Cobol s'est concentré sur les applications commerciales.
La collecte des ordures existait depuis la fin des années 50, c'est-à-dire bien avant C (début des années 70). GC nécessite une sécurité de la mémoire pour fonctionner correctement. Les langues avant et après C utilisaient GC comme fonctionnalité normale. Bien sûr, cela rend un langage beaucoup plus compliqué et peut-être plus lent, ce qui était particulièrement visible à l'époque des ordinateurs centraux. Les langages GC avaient tendance à être orientés vers la recherche (par exemple Lisp, Simula, ML) et / ou nécessitaient des postes de travail puissants (par exemple Smalltalk).
Avec des ordinateurs plus petits et plus puissants, l'informatique en général et les langages GC en particulier sont devenus plus populaires. Pour les applications en temps non réel (et parfois même alors), le GC est désormais l'approche préférée. Mais les algorithmes GC ont également fait l'objet d'intenses recherches. Comme alternative, une meilleure sécurité de la mémoire sans GC a également été développée, en particulier au cours des trois dernières décennies: les innovations notables sont RAII et les pointeurs intelligents en C ++ et le système de vie / vérificateur d'emprunt de Rust.
Java n'a pas innové en étant un langage de programmation à mémoire sûre: il a essentiellement pris la sémantique du langage Smalltalk GCed et à mémoire sûre et les a combinées avec la syntaxe et le typage statique de C ++. Il a ensuite été commercialisé comme un C / C ++ meilleur et plus simple. Mais ce n'est que superficiellement un descendant C ++. Le manque de pointeurs de Java est dû beaucoup plus au modèle objet Smalltalk qu'au rejet du modèle de données C ++.
Les langages "modernes" comme Java, Ruby et C # ne doivent pas être interprétés comme surmontant les problèmes des pointeurs bruts comme en C, mais doivent être considérés comme tirant leur origine de nombreuses traditions - y compris C, mais aussi de langages plus sûrs comme Smalltalk, Simula, ou Lisp.