Pointeurs et références

Écrit par Jean-Michel CHRISOSTOME. Publié dans Blog

Dans l'article précédent, nous avons défini ce qu'était une variable, une constante. Nous avons également introduit la notion de typage même présenté différents types de variables. Toutefois il existe encore d'autres types très importants en programmation et nous allons tâcher de les présenter dans cet article. Rappel sur les variables

Une variable c'est quoi?

Nous avons vu plus tôt qu'une variable représentait l'association entre un mot et une valeur. Nous avons vu également qu'une variable était définie par son type, qui va déterminer sa taille en octets et la manière de stocker et traiter les données contenues afin d'en interprêter la valeur.

Pour faire plus simple, une variable c'est donc un espace mémoire dédié au stockage d'une valeur auquel on associe un mot (ex: maVariable).

En C une variable se défini ainsi

 
/* On défini une variable nommée maVariable et on l'initialise avec la valeur 5 */
int maVariable=5;
 

En PHP une variable se défini ainsi

 
/* On défini une variable nommée $maVariable et on l'initialise avec la valeur 5 */
$maVariable=5;
 

En Javascript une variable se défini ainsi

 
/* On défini une variable nommée maVar et on l'initialise avec la valeur 5 */
var maVariable=5;
 

En Perl une variable se défini ainsi

 
# On défini une variable nommée maVariable et on l'initialise avec la valeur 5
my $maVariable=5;
 

Notez qu'il est important de toujours initialiser (attribuer une valeur) ses variables. Si vous ne le faîtes pas, vous pouvez vous retrouver avec des variables contenant des valeurs inconnues et non maîtrisées qui peuvent planter votre programme.

Un pointeur c'est quoi?

Un pointeur, c'est une variable qui va contenir en guise de valeur, l'adresse d'une autre variable. Par exemple:

 
En C un pointeur se défini comme suit:
/* On défini un pointeur nommé monPointeur et on le fait pointer vers l'adresse (adresse mémoire) d'une variable. */
int *monPointeur=&maVariable;
 

Le symbole & indique au compileur que nous ne voulons pas la valeur de la variable (soit 5) mais l'adresse mémoire à laquelle il a rangé cette valeur. Ainsi l'affichage de &maVariable pourrait donner 0x12aec345. (Correspond à une adresse mémoire en 32 bits)

Le symbole * précise que nous ne demandons pas la création d'une variable de type int, mais bien d'un pointeur dont l'adresse de destination va contenir une valeur de type int.

Quel est l'intérêt des pointeurs?

En C les pointeurs sont très utilisés pour donner aux fonctions (que nous étudierons plus tard) l'accès à de grosses quantités de données rapidement. il faut savoir que lorsqu'on appelle une fonction avec en paramètres des variables, nous ne donnons qu'une copie des valeurs contenues dans ces variables à la fonction. Elle ne peut que les utiliser pour faire des calculs ou d'autres copies, mais en aucun cas les modifier. C'est là qu'interviennent les pointeurs.

 
/* Illustration en C */
/* Dans ma variable Big, je stocke 1Go de données dans un type imaginaire */
monGrosType Big="1 Go de données";
 
/* Si je dois la donner en paramètre d'une fonction */
maFonction(Big);
 
/* le système va d'abord réaliser une copie locale de Big et donc consommer 1Go de mémoire en plus alors que ce n'est pas utile et en prime, il va consommer du temps processeur le temps de copier les 1Go de données. */
 

En résumé, nous perdons beaucoup de temps et beaucoup de mémoire pour une opération aussi anodine que l'éxécution d'une fonction. Soit quelque chose qui ne devrait pas prendre plus de quelques millisecondes sur un système moderne. Imaginez un peu sur les jeux vidéos moderne la perte de temps que cela représenterai si le système copiaît 1Go de donnée à chaque fois qu'un objet se déplace à l'écran en perdant plusieurs secondes. On serait loin des performances connues aujourd'hui.

 
/* Le même exemple avec un pointeur */
/* P_Big contient la position en mémoire du contenu de la variable Big */
monGrosType *P_Big=&Big;
 
/* Ici ma fonction est prévue pour travailller avec un pointeur */
maFonction(P_Big);
 
/* Elle récupère donc l'adresse contenu dans P_Big soit 4 octets en 32 bits et 8 octets en 64 bits. */
 

Vous admettrez qu'entre 8 octets max et 1Go la différence est toute faîte. Nous gagnons ici un temps processeur précieux et une quantité de mémoire non négligeable.

Les pointeurs sont spécifiques aux langages C et C++. Dans d'autres langages, on parle de référence, mais attention! Même si on retrouve quelques similarité, il ne s'agit pas de la même chose. Bien d'autres usages spécifiques sont réservés aux pointeurs, nous n'avons vu ici que la base.

Une référence c'est quoi?

Une référence est un type de variable qui partage quelques similarités avec les pointeurs, mais qui ne sont pas des pointeurs.

En PHP

 
<?php
/* Initialise le contenu de $maVariable avec "Beaucoup de blabla" */
$maVariable = "Beaucoup de blabla";
echo $maVariable; // Affichera: Beaucoup de blabla
 
/* Initialise le contenu de $bobVariable avec une copie du contenu de $maVariable */
$bobVariable = $maVariable;
 
echo $bobVariable; // Affichera: Beaucoup de blabla
 
/* Modifie le contenu de $bobVariable */
$bobVariable = "Coucou c'est Bob!";
 
echo $bobVariable; // Affichera: Coucou c'est Bob!
echo $maVariable; // Affichera encore: Beaucoup de blabla
 
/* Initialise le contenu de $totoVariable avec une référence vers $maVariable */
$totoVariable = &$maVariable;
 
echo $totoVariable; // Affichera: Beaucoup de blabla
 
/* Modifie le contenu référencé par $totoVariable */
$totoVariable = "Coucou c'est Toto!";
 
echo $totoVariable; // Affichera: Coucou c'est Toto!
echo $maVariable; // Affichera cette fois: Coucou c'est Toto!
?>
 

Nous constatons:

  • Que lorsqu'on modifie le contenu copié depuis une autre variable, cela n'affecte que le contenu de la copie, l'original reste intact.
  • Que lorsqu'on modifie le contenu référencé depuis autre variable, cela affecte le contenu de l'original car il n'y a pas création d'une copie. La zone mémoire pointée par $totoVariable est donc la même que $maVariable.
  • Qu'en PHP une référence vers une variable se fait en faisant précéder la variable d'un et commercial '&'
  • Pour simplifier, on peut dire que $totoVariable est un alias de $maVariable. Deux noms pointant vers un seul et même contenu. Comme en C, utiliser des références plutôt que des variables surtout sur des contenus lourds peut représenter un gain de temps et de mémoire lors de l'éxécution du script.

    En Javascript

     
    // Initialise le contenu de maVar avec Beaucoup de blabla
    var maVar = 'Beaucoup de blabla';
     
    console.log(maVar); // Affiche: Beaucoup de blabla
     
    // Initialise le contenu de $bobVar avec une copie de la valeur de maVar
    var bobVar = maVar;
     
    console.log(bobVar); // Affiche: Beaucoup de blabla
     
    // Modifie le contenu de la variable bobVar avec Salut c'est Bob
    bobVar = 'Salut, c\'est Bob!';
     
    console.log(bobVar); // Affiche: Salut, c'est bob!
    console.log(maVar); // Affiche: Beaucoup de blabla
     
    /* Sur un objet à présent les choses diffèrent */
    // Initialisation d'un objet vide
    var monObj={};
    // Initialisation de la propriété contenu avec Beaucoup de blabla
    monObj.contenu = 'Beaucoup de blabla';
     
    console.log(monObj.contenu); // Affiche: Beaucoup de blabla
     
    // Initialisation de l'objet bobObj avec une copie de monObj
    var bobObj = monObj;
     
    console.log(bobObj.contenu); // Affiche: Beaucoup de blabla
     
    // Modification du contenu référencé dans la copie de l'objet
    bobObj.contenu = 'Salut c\'est bob!';
     
    console.log(bobObj.contenu); // Affiche: Salut, c'est bob!
     
    console.log(monObj.contenu); // Affiche: Salut, c'est bob!
     

    Nous constatons:

    • Que le contenu d'une variable simple est copié mais que les éléments contenus dans les objets sont des références. La zone mémoire pointée par monObj.contenu et bobObj.contenu est donc la même.

    En Perl

     
    # Initialise le contenu de $maVar avec Beaucoup de blabla
    my $maVar = 'Beaucoup de blabla';
     
    # Initialise le contenu de la variable $bobVar avec le contenu de la variable $maVar
    my $bobVar = $maVar;
     
    print $bobVar."\n"; # Affiche: Beaucoup de blabla
     
    # Modification du contenu de la variable $bobVar
    $bobVar = "Salut c'est Bob!";
     
    print $bobVar."\n"; # Affiche: Salut c'est Bob
     
    print $maVar."\n"; # Affiche: Beaucoup de blabla
     
    # Initialise le contenu de la variable $totoVar avec une référence vers le contenu de $maVar
    my $totoVar = \$maVar;
     
    print $$totoVar."\n"; # Affiche: Beaucoup de blabla
     
    # Modifie le contenu référencé par $totoVar
    $$totoVar = "Salut c'est Toto!";
     
    print $$totoVar."\n"; #Affiche: Salut c'est Toto!
     
    print $maVar."\n"; #Affiche: Salut c'est Toto!
     

    Nous constatons:

    • Que lorsqu'on modifie le contenu copié depuis une autre variable, cela n'affect que le contenu de la copie, l'original reste intact.
    • Que lorsqu'on modifie le contenu référencé depuis une autre variable, cela affecte le contenu de l'original car il n'y a pas création d'une copie.
    • La zone mémoire piontée par $totoVar est donc la même que $maVar.
    • Qu'en Perl les références sont appelée en faisant précéder le nom de la variable par un antislash '\'
    • Qu'en Perl le contenu pointé par une référence s'appelle en faisant précéder le nom de la variable contenant une copie de la référence par un dollar '$'

    En conclusion de cet article, nous avons étudié les pointeurs qui sont propres en C et les références que vous pouvez retrouver dans de nombreux langages. Les références sont très utilisées dans le monde de la programmation car elles permettent de travailler sur des quantités de données très grandes sans avoir à copier systématiquement des contenus économisant ainsi du temps processeur et de la mémoire. Leur utilisation va bien au delà de ce qui est décrit dans cet article bien entendu, mais il s'agit ici de bases de programmation.

    Dans le prochain article nous allons parler des énumérations et des variables tableaux qui sont très utiles en programmation. En attendant, je vous laisse avec un peu de lecture.

    Liens et références