Pourquoi le maître C Dennis Ritchie a-t-il introduit des pointeurs en C? Et pourquoi les autres langages de programmation tels que VB.NET, Java ou C # les ont-ils éliminés? J'ai trouvé des points dans Google et je tiens également à écouter vos commentaires. Pourquoi éliminent-ils les concepts de pointeur dans les langues modernes?
Les gens disent que le langage C est le langage de base et que les pointeurs sont le concept qui rend le C puissant et remarquable et lui permet de rivaliser avec les langues plus modernes. Alors pourquoi ont-ils éliminé les pointeurs dans les langues plus modernes?
Pensez-vous que la connaissance des pointeurs est toujours importante pour les nouveaux programmeurs? De nos jours, les gens utilisent VB.NET ou Java, qui supporte des fonctionnalités plus avancées que le C (et n’utilise aucun concept de pointeur) et beaucoup de personnes que je vois maintenant (mes amis) choisissent ces langages en ignorant le C car ils prennent en charge des fonctionnalités avancées. Je leur dis de commencer par C. Ils disent que c'est un gaspillage d'apprendre les concepts de pointeurs lorsque vous faites des choses avancées dans VB.NET ou Java qui ne sont pas possibles dans C.
Qu'est-ce que tu penses?
Mis à jour le :
Les commentaires que j'ai lus sur Google sont:
Les ordinateurs précédents étaient trop lents et non optimisés.
L'utilisation de pointeurs permet d'accéder directement à une adresse, ce qui permet de gagner du temps au lieu d'en faire une copie lors d'appels de fonction.
La sécurité est nettement pire avec les pointeurs, raison pour laquelle Java et C # ne les ont pas inclus.
Celles-ci et quelques autres ce que j'ai trouvé. J'ai encore besoin de précieuses réponses. Ce serait grandement apprécié.
Réponses:
À cette époque, les développeurs travaillaient beaucoup plus près du métal. C était essentiellement un remplacement de niveau supérieur pour l'assemblage, qui est presque aussi proche du matériel que vous pouvez obtenir. Il était donc naturel que vous ayez besoin de pointeurs pour être efficaces dans la résolution des problèmes de codage. Cependant, les pointeurs sont des outils tranchants, qui peuvent causer des dommages importants s’ils sont utilisés sans précaution. De plus, l’utilisation directe de pointeurs ouvre la voie à de nombreux problèmes de sécurité, qui n’étaient pas un problème à l’époque (en 1970, Internet consistait en une douzaine de machines réparties dans quelques universités et il n’était même pas appelé ainsi. ...), mais est devenu de plus en plus important depuis. Ainsi, de nos jours, les langages de niveau supérieur sont délibérément conçus pour éviter les pointeurs de mémoire bruts.
Dire que "les choses avancées faites en VB.Net ou Java ne sont pas possibles en C" montre un point de vue très limité, pour le moins qu'on puisse dire :-)
Tout d’abord, toutes ces langues (même l’assemblage) sont complètes, donc en théorie, tout ce qui est possible dans une langue est possible. Il suffit de penser à ce qui se passe lorsqu’un morceau de code VB.Net ou Java est compilé et exécuté: il est finalement traduit en (ou mappé) sur du code machine, car c’est la seule chose que la machine comprend. Dans des langages compilés comme C et C ++, vous pouvez obtenir le corps complet du code machine équivalent au code source d'origine de niveau supérieur, sous la forme d'un ou plusieurs fichiers / bibliothèques exécutables. Dans les langages basés sur les machines virtuelles, il est plus difficile (et peut-être même impossible) d’obtenir la représentation complète du code machine équivalente de votre programme, mais elle existe toujours quelque part dans les profondeurs du système d’exécution et du JIT.
Maintenant, bien sûr, la question de savoir si une solution est réalisable dans une langue spécifique est une question totalement différente. Aucun développeur avisé ne commencerait à écrire une application Web dans l’assemblage :-) Mais il est utile de garder à l’esprit que la plupart ou la totalité de ces langages de niveau supérieur sont construits sur une énorme quantité de code de bibliothèque de classes et d’exécution, un grand qui est implémenté dans un langage de niveau inférieur, généralement en C.
Alors pour en venir à la question,
Le concept derrière les pointeurs est indirection . Ceci est un concept très important et, à mon humble avis, tout bon programmeur devrait le comprendre à un certain niveau. Même si quelqu'un travaille uniquement avec des langages de niveau supérieur, l'indirection et les références sont toujours importantes. Ne pas comprendre cela signifie être incapable d'utiliser toute une classe d'outils très puissants, ce qui limite sérieusement sa capacité à résoudre les problèmes à long terme.
Donc, ma réponse est oui, si vous voulez devenir un très bon programmeur, vous devez également comprendre les pointeurs (ainsi que la récursivité - c'est l'autre pierre d'achoppement typique des développeurs en herbe). Vous n’avez peut-être pas besoin de commencer avec cela - je ne pense pas que le C soit optimal comme langue maternelle de nos jours. Mais à un moment donné, il faut se familiariser avec l'indirection. Sans cela, nous ne pourrons jamais comprendre comment fonctionnent réellement les outils, les bibliothèques et les frameworks que nous utilisons. Et un artisan qui ne comprend pas le fonctionnement de ses outils est très limité. Assez bien, on peut aussi le comprendre dans les langages de programmation de niveau supérieur. Un bon test décisif consiste à implémenter correctement une liste doublement chaînée - si vous pouvez le faire dans votre langue préférée, vous pouvez affirmer que vous comprenez suffisamment bien le sens indirect.
Mais si ce n’est rien d’autre, nous devrions le faire pour apprendre le respect des anciens programmeurs qui ont réussi à construire des choses incroyables en utilisant des outils ridiculement simples qu’ils avaient (par rapport à ce que nous avons maintenant). Nous nous tenons tous sur les épaules de géants et il est bon que nous reconnaissions cela plutôt que de prétendre que nous sommes nous-mêmes les géants.
la source
Je pense que vous devez différer.
Java et d'autres langages de niveau supérieur n'ont pas supprimé les pointeurs. Ce qu'ils ont fait était de supprimer l'arithmétique simple du pointeur.
En fait, Java autorise toujours une arithmétique de pointeur protégée et restreinte : l'accès au tableau. En clair, l’accès à un tableau n’est que déréférencement. C'est une notation différente, un sucre syntaxique, si vous voulez, pour clairement communiquer ce que vous faites.
Pourtant,
array[index]
est équivalent à*(array+index)
. Pour cette raison, cela équivaut également àindex[array]
bien que je suppose que certains compilateurs C puissent vous avertir, si vous le faites.En corollaire,
pointer[0]
équivaut à*pointer
. C'est simplement parce que le "pointeur sur un tableau" est l'adresse de la première entrée du tableau et que les adresses des éléments suivants sont calculées en ajoutant l'index.En Java, les arithmétiques de type pointeur (référencement et déréférencement) n'existent plus. Cependant les pointeurs existent. Ils les appellent des références, mais cela ne change pas ce que c'est. Et l'accès au tableau est toujours exactement la même chose: regardez l'adresse, ajoutez l'index et utilisez cet emplacement de mémoire. Cependant, en Java, il vérifiera si cet index se situe ou non dans les limites du tableau que vous avez initialement alloué. Sinon, il lève une exception.
Maintenant, l'avantage de l'approche Java est que vous n'avez pas de code, cela écrit aveuglément des octets arbitraires dans des emplacements de mémoire arbitraires. Cela améliore la sécurité, mais aussi la sécurité, car si vous ne parvenez pas à vérifier les débordements de mémoire tampon, le moteur d’exécution le fera pour vous.
L'inconvénient est que c'est simplement moins puissant. Il est possible de faire de la programmation sécurisée en mémoire en C. Il est impossible de tirer profit de la rapidité et des possibilités de programmation non sécurisée en Java.
En réalité, les pointeurs et l'arithmétique des pointeurs ne posent aucun problème. Ils sont simplement expliqués de manière compliquée, alors qu'un pointeur est, c'est un index vers un tableau géant (votre espace mémoire), tout ce qui référence une valeur est de vous donner l'index où le trouver, tout ce que le déréférencement fait, c'est chercher la valeur à un index donné. (Ceci est juste un peu simplifié, car il ne prend pas en compte le fait que les valeurs sont de taille différente dans la mémoire, en fonction de leur type. Mais c'est un détail circonstanciel, plutôt qu'une partie du concept réel)
IMHO, tout le monde dans notre travail devrait être capable de comprendre cela, ou ils sont simplement dans le mauvais domaine.
la source
back2dos
eu raison la première fois, puisque(array + index)
prend déjà en compte la taille des objets (en C).array[index]
, et c'est*(array+index)
. Si vous voulez montrer comment le compilateur fait les choses en interne, vous pouvez explicitement parler d'octets ou donner l'assembly.Le concept de pointeurs est important dans l'ensemble des connaissances en programmation informatique. Comprendre le concept est bon pour les futurs programmeurs ou les programmeurs de n'importe quel langage, même si le langage ne le supporte pas directement.
Les pointeurs ont leur utilisation dans les structures de données (listes chaînées) et la conception de bases de données (clé étrangère).
Des langages tels que VB et C # peuvent transmettre des données par "référence" à des méthodes, ce qui peut être considéré comme un type de pointeur.
Comprendre où les données sont allouées en mémoire (pile contre tas) reste important pour l'efficacité des algorithmes.
À mon avis, il est important d’apprendre les bases.
la source
std::sort
,std::partition
,std::find
, Etc. Ils travaillent avec des pointeurs, et ils travaillent avec des objets qui agissent comme des pointeurs (itérateurs). Et ils travaillent sur n'importe quelle collection générale; listes liées, tableaux dynamiques,deque
s, arbres ou tout autre type de collection définie par l'utilisateur. Vous ne pouvez pas ce genre d'abstraction sans pointeurs.Oui, oui, oui, oui et oui !!!
Si vous ne connaissez pas les bases, vous ne pourrez JAMAIS résoudre les problèmes vraiment difficiles, étranges, difficiles et compliqués qui se présentent à vous.
Et si vous comprenez très bien les bases, vous êtes BEAUCOUP plus commercialisable sur le marché du travail.
J'ai déjà travaillé avec un type programmant depuis 10 ans et je ne savais pas comment les indicateurs fonctionnaient. Je (beaucoup plus junior) a passé des heures sur un tableau blanc à l'éduquer. Cela m'a ouvert les yeux. Il n'avait aucune idée de tant de choses fondamentales.
Savoir autant que possible.
la source
Oui, la compréhension est importante.
Il y a quelques mois, je programmais en C # et je voulais faire une copie d'une liste. Bien sûr, ce que j'ai fait a
NewList = OldList;
commencé à être modifiéNewList
. Lorsque j'ai essayé d'imprimer les deux listes, elles étaient identiques, puisqu'ilNewList
s'agissait simplement d'un pointeur surOldList
une copie et non d'une copie. J'étais donc toujours en train de changerOldList
. Cela ne m'a pas pris trop de temps pour le comprendre, mais certains de mes camarades de classe n'ont pas été aussi rapides et ont dû expliquer pourquoi cela se produisait.Exemple:
Et bien sûr, le résultat est le suivant:
Il n'est pas important de savoir comment les utiliser. Pourtant, les comprendre est crucial!
la source
NewList
était juste un pointeur surOldList
" - pour être précis, les deuxNewList
etOldList
n'étaient que des pointeurs, se référant au mêmeList
objet.b
ne contient plus de référence et qu'elle est maintenant fouillée.Pointer le concept! = Pointer l'arithmétique! = Pointer la syntaxe
La première importe toujours, si vous avez besoin (et vous avez) une compréhension de la copie profonde / superficielle, passe par référence / passe par valeur, etc. Les deux autres ne comptent que si votre langue du jour vous permet de les utiliser.
la source
a=[1,2]; b=a; a.append(3)
que les deuxa
etb
vont à la fois référence au même objet[1,2,3]
sans le savoir des choses comme dans C l'i
élément e d'un tableau peut être référencé pararr[i]
oui[arr]
comme les deux sont*(arr+i)
. Je préfère quand la langue ne se laissei[arr]
pas utiliser.Parce que les pointeurs sont un mécanisme très puissant qui peut être utilisé de nombreuses manières.
Parce que les pointeurs sont un mécanisme très dangereux qui peut être utilisé à bien des égards.
Je pense que les programmeurs devraient en apprendre davantage sur les indicateurs, mais d'un point de vue éducatif, il n'est pas sage de les présenter plus tôt. La raison en est qu’ils sont utilisés à des fins différentes, il est difficile de dire, en tant que débutant, pourquoi vous utilisez un pointeur dans certaines circonstances.
Voici une liste incomplète pour laquelle les pointeurs sont utilisés:
new T
)struct T { T* next; /* ... */ };
)for (T* p = &a[0]; p != &a[0] + n; ++p) { ... }
)T* new_pointer = existing_pointer;
)T* pointer_to_base = pointer_to_derived;
)mutate(&object);
)if (p) { /* ... */ }
)Notez que l’utilisation d’un seul mécanisme pour tous ces concepts démontre à la fois la puissance et l’élégance du programmeur expérimenté et le grand potentiel de confusion qui caractérise un débutant en programmation.
la source
Pourquoi? Vous pouvez écrire un système énorme avec un concepteur de formulaires et un générateur de code. N'est-ce pas suffisant? (ironie)
Et maintenant sérieusement, les pointeurs ne font pas partie intégrante de la programmation dans de nombreux domaines, mais ils permettent aux gens de comprendre le fonctionnement des internes. Et si nous n'avons personne qui comprend le fonctionnement des composants internes, il y aura une situation où SQL2020, Windows 15 et Linux 20.04 seront écrits dans une machine virtuelle gâchée, fonctionnant sur 30 couches d'abstraction, avec du code généré via IDE, en JavaScript .
Ce n'est certainement pas ce que je veux voir.
Alors oui, ils doivent le faire, certainement!
la source
Ni Java ni C # n'ont éliminé les pointeurs, ils ont des références presque identiques. Ce qui a été éliminé est l'arithmétique de pointeur, qui peut être omis dans un cours d'introduction.
Aucune application non triviale ne pourrait être réalisée sans le concept de pointeurs ou de références, il vaut donc la peine d'être enseignée (aucune allocation dynamique de mémoire ne pourrait être réalisée sans eux).
Considérez ce qui suit en C ++ et en Java, et je suppose que ce n'est pas très différent en C #: il
aClass *x = new aClass();
aClass x = new aClass();
n'y a pas vraiment trop de différence entre les pointeurs et les références, n'est-ce pas?
Les arithmétiques de pointeurs doivent être évitées sauf si nécessaire et lors de la programmation avec des modèles de haut niveau, il n'y a donc pas de gros problème.
la source
Le programmeur professionnel devrait maîtriser les pointeurs.
Les personnes qui souhaitent connaître la programmation doivent en apprendre davantage sur son existence et ses implications, mais ne doivent pas nécessairement les utiliser.
Les personnes qui souhaitent résoudre des problèmes personnels via la programmation (comme moi, qui utilisent beaucoup de scripts Python) peuvent très bien les ignorer.
Eh bien, c'est mon opinion ...; o)
la source
Les pointeurs d’adresses variables constituent un cas particulier du concept plus généralisé d’indirection. L'indirection est utilisée dans la plupart (toutes?) Des langues modernes dans de nombreuses constructions telles que les délégués et les callbacks. Comprendre le concept d'indirection vous permet de savoir quand et comment utiliser au mieux ces outils.
la source
Absufreakinglutely OUI ! Tous ceux qui programment doivent comprendre les pointeurs et l'indirection.
Les pointeurs indiquent comment accéder à de nombreuses données dans toutes les langues. Les pointeurs sont une fonctionnalité matérielle de tous les microprocesseurs. Les langages de haut niveau tels que Java, VB & C # interdisent essentiellement l’accès direct aux pointeurs des utilisateurs du langage référencé. Les références font référence à des objets via le schéma de gestion de la mémoire du langage (par exemple, un pointeur avec des métadonnées ou juste un nombre pour la table de mémoire).
Comprendre le fonctionnement des pointeurs est fondamental pour comprendre le fonctionnement réel des ordinateurs. Les pointeurs sont également plus souples et puissants que les références.
Par exemple, la raison pour laquelle les tableaux commencent à l'indice zéro est parce qu'ils sont en réalité un raccourci pour l'arithmétique de pointeur. Sans apprendre à comprendre le fonctionnement des pointeurs, de nombreux programmeurs débutants n’ont pas tout à fait accès aux tableaux.
La ligne 2 en arithmétique de pointeur serait:
Sans comprendre les pointeurs, on ne peut pas comprendre la gestion de la mémoire, la pile, le tas ou même les tableaux! De plus, il est nécessaire de comprendre les pointeurs et le déréférencement pour comprendre comment les fonctions et les objets sont transmis.
TL: DR : Comprendre les pointeurs est fondamental pour comprendre que les ordinateurs fonctionnent réellement .
la source
Je pense que cela se résume au fait que la nécessité de gérer les pointeurs a disparu, les programmeurs étant moins sensibles au matériel direct sur lequel ils tournaient. Par exemple, attribuez une structure de données de liste chaînée d’une manière qui s’ajuste parfaitement à la séquence de modules de mémoire de 640 octets du matériel spécialisé.
Traiter manuellement les pointeurs peut être sujet à des erreurs (entrainant des fuites de mémoire et du code exploitable) et prend beaucoup de temps pour bien faire les choses. Ainsi, Java et C #, etc. gèrent tous maintenant votre mémoire et vos pointeurs pour vous via leurs machines virtuelles (VM). Cela est sans doute moins efficace que l’utilisation de C / C ++ brut, bien que les machines virtuelles s’améliorent constamment.
C (et C ++) sont encore des langages largement utilisés, notamment dans les espaces de calcul hautes performances, de jeux et de matériel embarqué. Je suis personnellement reconnaissant d'avoir appris sur les pointeurs, car la transition vers les références Java (concept similaire aux pointeurs) était très facile et je ne m'étais pas égaré lorsque j'ai vu ma première NullPointerException (que l'on devrait vraiment appeler une NullReferenceException, mais je digresse). .
Je vous conseillerais de vous familiariser avec le concept des pointeurs car ils sous-tendent encore de nombreuses structures de données, etc. Ensuite, choisissez une langue dans laquelle vous aimez travailler, sachant que si quelque chose comme un NPE apparaît, vous savez ce qui se passe réellement. .
la source
C'est la vérité objective:
Certaines langues supportent l'accès direct à la mémoire (pointeurs), d'autres non. Il y a de bonnes raisons pour chaque cas.
Comme quelqu'un l'a dit ici, à l'époque de C, la gestion automatique de la mémoire n'était pas aussi complexe qu'aujourd'hui. Et les gens y étaient habitués, de toute façon. Les bons programmeurs de l'époque avaient une compréhension beaucoup plus profonde des programmes informatiques que celle de notre génération (j'ai 21 ans). Ils utilisent des cartes perforées et attendent des jours de compilation sur l’ordinateur central. Ils savaient probablement pourquoi chaque élément de leur code existait.
L'avantage évident des langages comme C est qu'ils vous permettent d'avoir un contrôle plus fin sur votre programme. Quand en avez-vous réellement besoin ces jours-ci? Uniquement lorsque vous créez des applications d'infrastructure, telles que des programmes liés au système d'exploitation et des environnements d'exécution. Si vous souhaitez simplement développer un bon logiciel, rapide, robuste et fiable, alors la gestion automatique de la mémoire est le plus souvent votre meilleur choix.
Le fait est que l’accès direct à la mémoire a été largement utilisé au cours de l’histoire du développement logiciel. Les utilisateurs avaient créé des programmes contenant des fuites de mémoire et étaient en réalité plus lents en raison d'une allocation de mémoire redondante (en C, il est facile et courant d'étendre l'espace mémoire virtuel du processus pour chaque allocation).
De nos jours, les machines virtuelles / runtimes font beaucoup mieux que 99% des programmeurs pour allouer et libérer de la mémoire. En plus de cela, ils vous permettent une flexibilité supplémentaire dans le flux que vous souhaitez que votre programme ait, parce que vous n'êtes (généralement) pas occupé à libérer de la mémoire allouée au bon moment et au bon endroit.
Quant à la connaissance. Je trouve admirable que les programmeurs sachent comment les environnements dans lesquels ils programment sont implémentés. Pas nécessairement dans les moindres détails, mais la grande image.
Je pense que savoir (au moins) comment fonctionnent les pointeurs est intéressant. Même chose que savoir comment le polymorphisme est implémenté. D'où vient le processus de votre processus et comment. Ce sont des choses qui m'ont toujours intéressé, personnellement. Honnêtement, je peux dire qu'ils ont fait de moi un meilleur programmeur, mais je ne peux pas dire que ce soit une nécessité éducative pour quiconque veut devenir un bon programmeur. Dans les deux cas, en savoir plus va souvent vous rendre meilleur dans votre travail.
Parce que même si vous ne connaissez pas tous les détails, quelqu'un qui le fera pourra transformer ce que vous aurez créé en quelque chose de plus performant. Et ce n'est souvent pas un travail difficile, une fois que vous avez une conception correcte, propre et testable (et c'est généralement l'essentiel du travail).
Si j'étais un intervieweur qui cherchait à embaucher quelqu'un pour une application linguistique de haut niveau, ce seraient les choses qui m'intéresseraient le plus.
La connaissance de bas niveau est un bonus. C'est bon pour le débogage et parfois pour créer des solutions légèrement meilleures. Cela fait de vous une personne intéressante, professionnellement. Cela vous accorde un peu de respect sur votre lieu de travail.
Mais dans le monde d'aujourd'hui, ce n'est pas une exigence sacrée.
la source
Dans la plupart des cas, dans les langages OO de haut niveau, la compréhension des références suffit, vous n'avez pas vraiment besoin de comprendre comment ces langages implémentent les références en termes de pointeurs.
Il existe des approches multi-paradigmes plus fonctionnelles et modernes que j'apprécierais beaucoup plus que de pouvoir faire de l'arithmétique de pointeur de fantaisie, c'est-à-dire écrire la 1000e fonction de copie de chaîne optimisée, dont les performances sont probablement pires que celle de String.copy de votre bibliothèque std.
Je conseillerais d’apprendre d’abord beaucoup plus de concepts différents et de niveau supérieur, puis de choisir des langues de conceptions différentes pour élargir votre horizon avant d’essayer de vous spécialiser dans le domaine du matériel.
Je vois souvent des tentatives totalement infructueuses de micro-optimiser un servlet Web ou un code similaire pour un gain de 5%, lorsque la mise en cache (mémorisation), l'optimisation SQL ou simplement le réglage de la configuration du serveur Web peut produire 100% ou plus avec peu d'effort. Utiliser la plupart des pointeurs est une optimisation prématurée dans la plupart des cas.
la source
En définitive, nous devons avoir un concept approfondi de pointeur, si vous voulez vraiment être un bon programmeur. Le concept de pointeur était un accès direct à votre valeur qui devient plus efficace avec les contraintes de temps ...
De plus, maintenant que nous considérons les applications mobiles, qui ont une mémoire très limitée, nous devons l’utiliser avec précaution pour que son fonctionnement soit très rapide avec la réponse de l’utilisateur ... Pour cela, nous avons besoin d’une référence directe à la valeur ...
Prenons les périphériques Apple, ou le langage Objective C, qui fonctionne totalement avec le concept de pointeur uniquement. Toute la variable déclarée dans l’objectif C a un pointeur. Vous devez passer par le wiki de Objective C
la source