Introduction aux pointeurs [C / C++]<span class="wtr-time-wrap after-title"><span class="wtr-time-number">12</span> min read</span>
Le fonctionnement des pointeurs

Introduction aux pointeurs [C / C++]12 min read

Vous venez de commencer C ou C++ et vous êtes complètement perdu avec les pointeurs ? C’est normal , les pointeurs sont des outils très complexes réservés aux langages très techniques comme C ou C++. Dans cet article on va voir comment manier des pointeurs pour avoir un code plus qualitatif.

Avant toute chose, j’aimerais vous rassurer, si vous avez le sentiment de ramer, c’est normal. Pour ma part j’ai appris le C et le C++ respectivement en 5ème et 6ème langage. Et je me suis heurté a quelque chose de très complexe. J’avais l’habitude des variables non typés et de ne pas avoir à gérer la mémoire. Et la je tombe sur un langage ou il est VITAL d’avoir ces compétences pour ne pas créer de bugs.

Grâce à des schémas et des explications on va voir le fonctionnement des pointeurs ainsi que leur intérêt, vous allez voir qu’ils permettent de faire des choses incroyables.

Comment ça fonctionne les pointeurs ?

Avant même de voir comment on peux mettre en place et utiliser les pointeurs, on va voir comment ils fonctionnent. Pour ça on va devoir se plonger dans le fonctionnement de la mémoire d’un ordinateur. Ne vous inquiétez pas, ça as l’air très complexe mais au final, c’est plutôt simple.

Le fonctionnement des variables

Les pointeurs permettent de faire un lien à des variables, on dis qu’ils pointent vers les variables. Il est donc essentiel de comprendre comment fonctionnent les variables et comment elles sont stockées dans la mémoire afin de saisir le fonctionnement des pointeurs.

Vous savez, dans des langages comme PHP ou Java, on ne s’embête pas avec la mémoire, il y a un système de création automatique et de garbage collection pour la création et la supression des variables. Néanmoins, en C et C++ on dois gérer manuellement la taille de chaque variable, j’entends par taille la place qu’elle prends dans la mémoire.

Cette gestion manuelle as des avantages, elle permets d’optimiser un maximum les performances du programme, puisque celui-ci n’utilise que les ressources dont il as besoin.

Voyons grâce à un schéma comment sont stockées les variables dans la mémoire, que ce soit dans le heap ou dans la stack.

Comment est stockée une variable dans la mémoire RAM
Comment est stockée une variable dans la mémoire RAM

On voit qu’une variable se décompose en 3 parties, d’abord on as le nom de la variable. C’est ce que vous tapez dans le programme. Ensuite on as la valeur de la variable , c’est ce par quoi le nom sera remplacé dans le programme. Si vous tapez “num” , ce mot clé sera remplacé par 10.

Enfin, on as l’adresse de la variable, la partie la plus intéressante et la plus complexe aussi. Pour se faire, il faut comprendre que la mémoire RAM, c’est juste un tableau qui stocke des valeurs. Ce tableau as des adresse, semblables à des indexes. Et chaque index corresponds à une valeur.

Ainsi la position X correspondras à la valeur d’une variable et la position Y à une autre.

C’est quoi un pointeur ?

Si vous avez cherché sur google , “comment fonctionnent les pointeurs”, c’est probablement que vous maîtrisez déjà le fonctionnement des variables. Si ce n’était pas le cas, maintenant ça l’est.

Un pointeur c’est une variable qui fait référence à une autre variable. C’est très abstrait comme définition, je vous l’accorde.L’idée d’un pointeur, c’est de pouvoir modifier une variable X à partir d’une variable Y.

Donc la valeur d’un pointeur, c’est l’adresse d’une autre variable.

Le fonctionnement des pointeurs
Le fonctionnement des pointeurs

J’ai encore piqué le schéma à openclassroom parce que je le trouve clair et abordable. On voit qu’il existe une variable age avec une valeur de 10. Cette variable as une adresse qui correspond à sa place dans la mémoire.

On voit ensuite une deuxième variable, celle-ci est spéciale puisque c’est un pointeur. On voit qu’elle as pour valeur l’adresse de notre variable age.

Donc il suffit de modifier la valeur du pointeur pour modifier la variable ?

Et bien non, c’est le piège classique. La valeur de notre pointeur c’est l’adresse de notre variable age, donc si on modifie cette valeur, on va simplement perdre l’adresse de notre variable.

En C ou C++ , on ne va pas directement modifier la valeur de notre pointeur mais dire a notre programme de modifier la valeur de la variable qui possède l’adresse de notre pointeur.

Comment on utilise les pointeurs

Assez de théorie, commençons à pratiquer. Dans cet article je vais utiliser du C, si vous faites du C++ pas de soucis, sachez juste que la fonction printf correspond a cout.

#include <stdio.h>

int main() {
    int age = 20; // création d'une variable
    int *pointeurage = &age; // création d'un pointeur qui as pour valeur l'index de la variable age
    printf("%d", *pointeurage); // affichage de la valeur de la variable age via le pointeur
    return 0;

}

Décomposons ce code afin de comprendre comment on utilise les pointeurs.

D’abord on déclare une variable age , celle ci est un int et as une valeur de 20, jusque la rien d’extraordinaire. Ensuite, on déclare un pointeur, comme vous le voyez ils ne possèdent pas de type. A la place on utilise “*” devant le nom de la variable. Une fois le pointeur crée, on initialise sa valeur a l’index de notre variable age.

Pour se faire on affiche l’index de notre variable age. Pour faire ceci on utilise “&”. Lorsque l’on utilise ce signe devant une variable , on affiche non pas sa valeur mais son index. Donc on crée un pointeur et on lui donne comme valeur l’index de notre variable age , plutôt simple non ?

Une fois ce pointeur crée, c’est très simple. On peux faire 3 choses avec notre pointeur :

  • Afficher la valeur du pointeur , c’est à dire l’index de la variable pointée. Pour se faire , utilisez simplement le pointeur sans indiquer aucun symbole.
  • Afficher l’index de notre pointeur, puisque c’est une variable, ce pointeur possède aussi un index et il est possible d’afficher cet index, avec “&”. Il est d’ailleurs possible d’afficher l’index de n’importe quelle variable avec ce symbole
  • Enfin on peux afficher et modifier la valeur de la variable pointée. C’est d’ailleurs la choses la plus intéressante avec les pointeurs. Pour se faire, on utilise “*” , exactement comme quand on déclare le pointeur. C’est d’ailleurs ce qu’on fait au printf

Voyons la dernière ligne interessante, le printf. C’est une fonction permettant d’afficher quelque chose sur la console (je précise pour les développeurs C++). On voit qu’on utilise l’étoile devant notre pointeur, cela va avoir pour effet d’afficher la valeur de notre variable pointée, donc ce petit programme va renvoyer 20. C’est à dire la valeur de la variable age.

A quoi servent les pointeurs ?

Ce n’est pas évident comme question. A première vue, on as l’impression que les pointeurs ne sont que des fonctionnalités annexes utiles dans seulement certaines situations. Et bien vous vous trompez.

Pour vous prouver que les pointeurs sont très utiles, prenons ce code :

void modifier_age(int age);

int main() {
    int monage = 20;
    modifier_age(monage);
    printf("%d", monage);
    return 0;

}

void modifier_age(int age) {
    age = 30;
}

Ici on passe une variable à une fonction et on essaye de la modifier, puis on retourne dans main et on affiche la valeur. Et la , vous en vous doutez peut être, cela ne fonctionne absolument pas. Pourquoi ? Et bien parce que lorsque nous donnons une variable à une fonction, on donne en faite une copie de cette variable, on ne modifie donc jamais la variable originale.

Pour pallier à ce problème on as deux solutions, utiliser return ou alors utiliser les pointeurs. Voyons d’abord la manière classique qui utilise return

#include <stdio.h>

int modifier_age(int age);

int main() {
    int monage = 20;
    monage = modifier_age(monage);
    printf("%d", monage);
    return 0;

}

int modifier_age(int age) {
    return age + 10;
}

Ici, on va simplement modifier notre variable en ajoutant 10. On utilise simplement return pour retourner une nouvelle valeur qui correspond a l’ancienne + 10.

Cette méthode fonctionne parfaitement bien, sauf si on veux modifier plusieurs variables en même temps, la c’est strictement impossible car return ne renvoi qu’une seule variable.

Pour palier à ça , voyons la méthode pointeur

#include <stdio.h>

void modifier_age(int *age);

int main() {
    int monage = 20;
    modifier_age(&amp;monage);
    printf("%d", monage);
    return 0;

}

void modifier_age(int *age) {
    *age += 10;
}

Ici, au lieu de retourner la valeur de notre nouvelle variable et de l’assigner à notre ancienne variable. On fait beaucoup plus simple, on modifie directement la valeur de notre variable en utilisant un pointeur et en passant à la fonction non pas une copie de la variable mais directement l’adresse de la variable.

Ce qui es génial c’est que l’on as pas à réassigner notre variable “monage”et que l’on as plus à retourner quelque chose depuis notre fonction modifier_age.

Je vous ai parlé toute à l’heure du fait qu’on pouvais modifier plusieurs variables en même temps, ce qui est impossible sans les pointeurs. Voyons maintenant comment on fait ça.

#include <stdio.h>

void modifier_age_telephone(int *age, long int *telephone);

int main() {
    int monage = 20;
    long int montelephone = 233839393;
    modifier_age_telephone(&amp;monage , &amp;montelephone);
    printf("l'age est de %d et le telephone %d", monage, montelephone);
    return 0;

}

void modifier_age_telephone(int *age, long int *telephone) {
    *age += 10;
    *telephone = 1234567;
}

Voici un code un peu plus complexe mais loin d’être impossible à comprendre. Dans le cas suivant, on déclare deux int et on leur assigne une valeur. Ensuite on appelle la fonction “modifier_age_telephone” en envoyant les index de nos deux variables.

Dans notre fonction , on modifie simplement la valeur des variables via des pointeurs. Et on obtient ce résultat :

l'age est de 30 et le téléphone 1234567

On voit ici que nos deux variables ont étés modifiés dans une même fonction, génial non ? Cela semble absurde mais c’est impossible à faire sans les pointeurs.

Mettre en place les pointeurs

Je vais maintenant vous parler de comment sont utilisés les pointeurs en C / C++. Sachez que l’on utilise très rarement voir jamais return. En faite, on utilise return uniquement pour indiquer 0 ou 1 c’est à dire échec ou réussite de la fonction. Lorsque l’on as à modifier une ou plusieurs valeurs, on va utiliser des pointeurs afin de pouvoir modifier toutes ces valeurs et de ne pas avoir a utiliser de return.

Je vous recommande vraiment d’utiliser les pointeurs plutôt que return. Pourquoi ? Et bien car return ajoute plus de code dans votre programme et soyons franc, c’est clairement indésirable d’écrire plus de code pour arriver au même résultat.

En plus de cela, on envoi systématiquement une copie de notre variable lorsque l’on exécute une fonction. Ce qui as tendance à surcharger la mémoire.

Et enfin le plus intéressant, il est possible de modifier la valeur de plusieurs variables dans une seule fonction.

Utiliser les listes

J’ai un secret à vous révéler, les listes sont en fait des pointeurs. En fait une liste c’est simplement une adresse et un type. Par exemple un int représente 4 bits, donc un array a la position 1000 va en faite donner :

liste[0] = position 1000 , liste[1] = position 1004 , liste[2] = position 1008. En indiquant l’index que vous recherchez, le programme va simplement faire une addition en prenant l’index initial de notre array c’est à dire sa position, et en ajoutant ensuite X pour chaque index passés , X dépends bien sur du type de variable

En quoi c’est important ? Et bien , les arrays ne sont pas des structures réelles, seulement une valeur d’adresse pour la position 0, et ensuite les autres positions sont simplement les adresses suivantes. C’est donc très important car si j’ai un array de 3 int donc 12 bytes, et bien si j’essaie d’accéder à la position [4] , qui n’existe pas, et bien on va accéder à une variable extérieur à l’array, ce qui peux causer des overflow. Il faut donc faire très attention lorsque l’on manipule les listes.

Conclusion

Comme vous l’avez vu, les pointeurs permettent de gérer bien plus facilement l’envoi de variables à des fonctions. Que ce soit pour réduire la compléxité du code en supprimant les return ou encore en modifiant plusieurs variables à la fois, les pointeurs permettent de créer du code bien plus simple à manier.

Si cet article vous as plu, vous pouvez vous abonner à ma newsletter pour recevoir le guide GRATUIT Ultime pour bien débuter la programmation

Vous abonner à notre newsletter

* champ requis

Au plaisir de vous revoir sur mon blog !

Laisser un commentaire

Fermer le menu
×
×

Panier