Une introduction aux pointeurs pour les programmeurs

  • Owen Little
  • 0
  • 3050
  • 376
Publicité

Que vous vous en rendiez compte ou non, la grande majorité des programmes que vous avez utilisés utilisent des pointeurs d'une manière ou d'une autre. Peut-être avez-vous vécu une NullPointerException à un moment donné. En tant que programmeur, le code que vous écrivez utilisera probablement des pointeurs, même si vous ne les avez pas mis en œuvre vous-même..

Aujourd'hui, je vais vous montrer comment fonctionnent les pointeurs. Par conséquent, vous voudrez peut-être vérifier le fonctionnement des tableaux et des listes. Fonctionnement des tableaux et des listes en Python Mode d'utilisation des tableaux et des listes en Python Les tableaux et les listes figurent parmi les structures de données les plus utiles en programmation: - Bien que peu de gens les utilisent au maximum de leurs possibilités. pour une introduction à la programmation. Cet article sera plus théorique que d'habitude, mais restez-y, les pointeurs sont très complexes!

Code de compilation

Avant de creuser dans les pointeurs, vous devez comprendre comment le code est construit et exécuté - vous le savez peut-être déjà. Cette section aura des déclarations assez générales - les choses qui s’appliquent au majorité des langues, mais pas nécessairement toutes.

Reprenons les choses au début. Chaque ordinateur utilise le binaire Qu'est-ce que le binaire? [Technologie expliquée] Qu'est-ce que le binaire? [Technologie expliquée] Etant donné que le binaire est si fondamental pour l’existence des ordinateurs, il semble étrange que nous n’ayons jamais abordé le sujet auparavant. C’est pourquoi aujourd’hui je pensais donner un bref aperçu de ce que binaire…, une série des uns et des zéros qui composent la technologie moderne telle que nous la connaissons. Il est extrêmement difficile de coder quoi que ce soit en binaire (les fichiers seraient très déroutants), car ce sont les instructions brutes nécessaires à votre ordinateur. unité centrale de traitement ou un processeur pour fonctionner Qu'est-ce qu'un processeur et que fait-il? Qu'est-ce qu'un processeur et que fait-il? Les acronymes informatiques sont source de confusion. Qu'est-ce qu'un processeur quand même? Et ai-je besoin d'un processeur quad ou dual-core? Qu'en est-il d'AMD ou d'Intel? Nous sommes là pour vous aider à expliquer la différence! . Ceci est connu comme Langage machine.

La prochaine étape à partir du code machine est Assemblée. C'est un format quelque peu lisible par l'homme. Bien que la programmation soit encore complexe, c'est possible. L’ensemble est composé d’une série de commandes simples permettant d’exécuter des tâches. Il est appelé niveau faible langage de programmation. Il est possible d’écrire des programmes complexes, mais il est difficile d’exprimer des concepts abstraits et demande beaucoup de réflexion..

Beaucoup de jeux vidéo et d’applications hautes performances ont une partie de la logique écrite lors de l’assemblage, car certaines augmentations de vitesse peuvent être trouvées si vous savez ce que vous faites. Cependant, pour la grande majorité des projets de programmation, vous n'avez pas besoin de connaître d'assemblage..

Ainsi, si le code machine est trop difficile à écrire et que l’assemblage est trop difficile à programmer, avec quoi écrivez-vous? Voici où haut niveau les langues entrent en jeu. Les langues de haut niveau rendent les programmes faciles à écrire. Vous pouvez programmer dans quelque chose qui ressemble à votre langue maternelle, et il est facile d’exprimer des algorithmes complexes. Vous avez peut-être entendu parler de nombreux langages de haut niveau (et vous aurez certainement utilisé un programme écrit en eux):

  • DE BASE
  • C++
  • Zézayer

Ces langues sont très anciennes maintenant et beaucoup ont été développées au début des années 1950! Presque tous les langages de programmation modernes sont des langages de haut niveau, y compris PHP et Python. De plus en plus de langues sont inventées chaque jour (même s’il en existe probablement assez à présent), mais comment fonctionne exactement votre code, même si un ordinateur nécessite un code machine??

Voici où la compilation entre en jeu. Un compilateur est un programme qui convertit votre code de haut niveau en une forme pouvant être exécutée. Cela pourrait être un autre langage de haut niveau, mais il s’agit généralement d’assemblage. Certains langages (tels que Python ou Java) convertissent votre code en une étape intermédiaire appelée bytecode. Cela nécessitera une nouvelle compilation à une date ultérieure, ce qui est généralement fait à la demande, par exemple lorsque le programme est exécuté. Ceci est connu comme juste à temps compilation, et c'est assez populaire.

Gestion de la mémoire

Maintenant que vous savez comment fonctionnent les langages de programmation, examinons la gestion de la mémoire dans les langages de haut niveau. Pour ces exemples, je vais utiliser un pseudo-code - code écrit non dans un langage spécifique, mais utilisé pour montrer des concepts plutôt que la syntaxe exacte. Aujourd'hui, cela ressemblera surtout au C ++ car c'est le meilleur langage de haut niveau (à mon avis).

Pour cette section, cela vous aidera si vous comprenez le fonctionnement de la RAM. Guide rapide et sale de la RAM: Ce que vous devez savoir Guide rapide et sale de la RAM: Ce que vous devez savoir La RAM est un élément crucial de tout ordinateur. , mais cela peut être déroutant. Nous décomposerons en termes faciles à comprendre, vous comprendrez. .

La plupart des langues ont des variables - des conteneurs qui stockent des données. Vous devez définir explicitement le type de données. Certains langages à typage dynamique tels que Python ou PHP gèrent cela pour vous, mais ils doivent le faire..

Disons que vous avez une variable:

int myNumber;

Ce code déclare une variable appelée mon numéro, et lui donne un type de données de entier. Une fois compilé, l'ordinateur interprète cette commande comme suit:

“Trouver de la mémoire vide et réserver un espace assez grand pour stocker un entier”

Une fois cette commande exécutée, ce bit de mémoire ne peut plus être utilisé par un autre programme. Il ne contient pas encore de données, mais il est réservé à votre variable myNumber..

Assignez maintenant une valeur à votre variable:

myNumber = 10;

Pour terminer cette tâche, votre ordinateur accède à son emplacement de mémoire réservé et modifie, quelle que soit la valeur qui y est stockée, cette nouvelle valeur..

Maintenant, c'est très bien, mais comment les emplacements de mémoire ne sont-ils pas réservés? Si les programmes réservaient toute la mémoire qu’ils appréciaient, la mémoire vive se remplirait immédiatement - ce qui en ferait un très système lent.

Pour éviter ce problème potentiel, de nombreuses langues implémentent une Éboueur, utilisé pour détruire les variables (et donc libérer les emplacements de mémoire réservés) qui ont disparu hors de portée.

Vous vous demandez peut-être ce qu'est la portée et pourquoi c'est si important. Scope définit les limites et la durée de vie des variables ou de la mémoire utilisée par un programme. Une variable est “hors de portée” lorsqu'il n'est plus accessible par aucun code (c'est à ce moment-là que le ramasse-miettes intervient). Voici un exemple:

fonction maths () int firstNumber = 1;  int secondNumber = 2; print (firstNumber + secondNumber); // ne fonctionnera pas

Cet exemple ne compilera pas. La variable firstNumber est dans le mathématiques fonction, donc c'est sa portée. Il est impossible d'y accéder de l'extérieur de la fonction dans laquelle il a été déclaré. C'est un concept de programmation important, et comprendre, il est essentiel de travailler avec des pointeurs.

Cette façon de gérer la mémoire est appelée la empiler. C'est la façon dont la grande majorité des programmes fonctionnent. Vous n'avez pas besoin de comprendre les indicateurs pour l'utiliser, et c'est assez bien structuré. L'inconvénient de la pile est la vitesse. Comme l'ordinateur doit attribuer de la mémoire, garder une trace des variables et exécuter le nettoyage de la mémoire, il y a une petite surcharge. C'est bien pour les petits programmes, mais qu'en est-il des tâches hautes performances ou des applications gourmandes en données??

Entrez: pointeurs.

Pointeurs

En surface, les indicateurs semblent simples. Ils font référence (pointer vers) un emplacement en mémoire. Cela peut ne pas sembler différent de “régulier” variables sur la pile, mais croyez-moi, il y a une énorme différence. Les pointeurs sont stockés sur le tas. C'est le contraire de la pile - c'est moins organisé, mais c'est beaucoup plus rapide.

Regardons comment les variables sont assignées sur la pile:

int numberOne = 1; int numberTwo = numberOne;

C'est une syntaxe simple. La variable numéro deux contient le numéro un. Sa valeur est copiée au cours de la cession de la numéro un variable.

Si vous vouliez avoir le adresse mémoire d'une variable, au lieu de sa valeur, vous devez utiliser le signe esperluette (&). Ceci est appelé le adresse de opérateur, et est une partie essentielle de votre boîte à outils de pointeur.

int numberOne = 1; int numberTwo = & numberOne;

Maintenant le numéro deux variable points dans un emplacement de mémoire, plutôt que de copier le numéro un dans son propre emplacement de mémoire. Si vous deviez sortir cette variable, ce ne serait pas le numéro un (même si cela est stocké dans l'emplacement de mémoire). Il afficherait son emplacement mémoire (probablement environ 2167, bien que cela varie en fonction du système et de la mémoire RAM disponible). Pour accéder à la valeur stockée dans un pointeur, au lieu de l'emplacement de la mémoire, vous devez déréférence le pointeur. Ceci accède directement à la valeur, ce qui serait le numéro un dans ce cas. Voici comment vous déréférence un pointeur:

int numberTwo = * numberOne;

le opérateur de déréférence est un astérisque (*).

Cela peut être un concept difficile à comprendre, alors reprenons-le:

  • le adresse de l'opérateur (&) stocke l'adresse mémoire.
  • le opérateur de déréférence (*) accède à la valeur.

La syntaxe change légèrement lors de la déclaration de pointeurs:

int * myPointer;

Le type de données de int se réfère ici au type de données du pointeur points to, et non le type du pointeur lui-même.

Maintenant que vous savez ce que sont les pointeurs, vous pouvez réaliser de très astuces avec eux! Lorsque la mémoire est utilisée, votre système d'exploitation démarre. séquentiellement. Vous pouvez penser à la RAM comme un casier. Beaucoup de trous pour stocker quelque chose, un seul peut être utilisé à la fois. La différence est que ces casiers sont tous numérotés. Lors de l’affectation de la mémoire, votre système d’exploitation démarre au numéro le plus bas et progresse. Il ne sautera jamais entre des nombres aléatoires.

Lorsque vous travaillez avec des pointeurs, si vous avez affecté un tableau, vous pouvez facilement naviguer vers l'élément suivant en incrémentant simplement votre pointeur..

Voici où ça devient intéressant. Lorsque vous transmettez des valeurs à une fonction (à l'aide de variables stockées dans la pile), ces valeurs sont copiées dans votre fonction. Si ce sont de grandes variables, votre programme les stocke maintenant deux fois. Lorsque votre fonction est terminée, vous aurez peut-être besoin d'un moyen de renvoyer ces valeurs. Les fonctions ne peuvent généralement renvoyer qu’une chose - qu’en est-il si vous voulez renvoyer deux, trois ou quatre choses?

Si vous passez un pointeur sur votre fonction, seule l'adresse de la mémoire est copiée (ce qui est minuscule). Cela évite beaucoup de travail à votre CPU! Peut-être que votre pointeur pointe vers un énorme tableau d'images - non seulement votre fonction peut-elle fonctionner avec exactement les mêmes données stockées dans le même emplacement de mémoire, mais une fois que c'est fait, il n'est pas nécessaire de retourner quoi que ce soit. Soigné!

Vous devez cependant faire très attention. Les pointeurs peuvent toujours sortir du cadre et être récupérés par le ramasse-miettes. Les valeurs stockées en mémoire ne sont toutefois pas collectées. Ceci s'appelle une fuite de mémoire. Vous ne pouvez plus accéder aux données (les pointeurs ayant été détruits), mais la mémoire est toujours utilisée. C’est une raison courante pour laquelle de nombreux programmes se bloquent et peuvent échouer de façon spectaculaire s’il ya une grande quantité de données. La plupart du temps, votre système d'exploitation tuera votre programme si vous avez une fuite importante (utilisez plus de RAM que le système), mais ce n'est pas souhaitable..

Le débogage des pointeurs peut être un cauchemar, en particulier si vous travaillez avec de grandes quantités de données ou si vous travaillez en boucle. Leurs inconvénients et leur difficulté à comprendre valent vraiment les compromis que vous gagnez en performance. Bien que rappelez-vous, ils ne sont pas toujours nécessaires.

C'est tout pour aujourd'hui. J'espère que vous avez appris quelque chose d'utile sur un sujet complexe. Bien sûr, nous n'avons pas couvert tout ce qu'il y a à savoir - c'est un sujet très complexe. Si vous souhaitez en savoir plus, je vous recommande vivement C ++ dans 24 heures..

Si cela vous semble un peu complexe, consultez notre guide des langages de programmation les plus simples. 6 Langages de programmation les plus faciles à apprendre pour les débutants processus d'édification. Voici les six langages de programmation les plus faciles pour les débutants. .

Avez-vous appris comment fonctionnent les pointeurs aujourd'hui? Avez-vous des conseils et astuces que vous souhaitez partager avec d'autres programmeurs? Sautez dans les commentaires et partagez vos pensées ci-dessous!




Personne n'a encore commenté ce post.

De la technologie moderne, simple et abordable.
Votre guide dans le monde de la technologie moderne. Apprenez à utiliser les technologies et les gadgets qui nous entourent chaque jour et à découvrir des choses intéressantes sur Internet.