Logo creanet 2.0
Les pointeurs et la gestion des adresses


Nous y voici enfinSmiley souris Préparez-vous à comprendre pas mal de choses d'un coup, ce chapitre sera beaucoup théorique mais c'est l'un des plus important!

Les pointeurs sont partout en programmation. Absolument partout! Vous en avez même utilisé ,sans le savoir, dès le chapitre sur les flux d'entrées et de sortieSmiley souris

Le but de ce chapitre est donc de vous expliquer ce que sont les pointeurs, à quoi ils servent et surtout comment s'en servirSmiley souris


Les pointeurs, une histoire ... de mémoire

La mémoire vive:

Tout d'abord, redéfinnissons ensemble comment est présentée la mémoire vive et coment elle fonctionne.
Nous avons vu précedemment que la mémoire vive permettait de stocker des informations temporaires (les variables). Seulement, savez-vous comment l'odinateur sait où trouver chaque variable dans son immense mémoire vive? Non? Et bien nous allons le découvrir iciSmiley souris


Les adresses

Le fonctionnement de la mémoire vive est assez simple. Imaginez qu'une maison représente une variable, et que le monde entier représente la taille de mémoire vive. Vous avez vu le nombre de maison?! L'ordinateur ne pourrait jamais retrouver une variable (=maison) dans la mémoire (=le monde)! Mais heureusement, pour pallier ce problème on a inventé quelque chose de simple et d'efficace: les adresses.

C'est comme pour les maisons! Comment trouve-t-on une maison en particulier? Grâce à son adresse! Et bien comment retrouve-t-on où est stockée une variable dans la mémoire vive? Grâce à son adresseSmiley rigole Regardez ce schéma pour mieux comprendre à quoi ressemble la mémoire vive de votre ordinateur:

 
memoire vive schema
A gauche, ce sont les adresses (elles vont beaucoup plus loin que 5 025 453 158, il y en a un nombre immenseSmiley souris). Et à chaque adresse correspond un endroit de libre où l'on peut y stocker une variable. Attention, j'ai bien dis y stocker une seule variable. Une variable n'étant qu'un chiffre (une lettre est aussi un chiffre et donc un mot, une suite de chiffre)
 
on ne peut stocker qu'un seul chiffre par emplacement mémoire.

Donc lorsque vous déclarez une variable, voici ce qui se passe en mémoire:

1) Le programme demande à l'ordinateur s'il peut prendre une partie de sa mémoire.

2) L'ordinateur accepte en lui indiquant l'adresse d'un emplacement mémoire qu'il pourra utiliser.

3) Le programme mémorise l'adresse.


Comprenez bien que les noms que vous donnez aux variables ne sont en réalité que des adresses. On a donné la possibilité de leur mettre des noms dans le code source juste afin de s'y retrouverSmiley souris


Du coup, lorsque vous aurez, dans la suite du programme, besoin de cette variable, le programme ira tout simplement à l'adresse indiquéeSmiley souris


Se servir des adresses

Nous allons maintenant voir comment afficher l'adresse d'une variableSmiley souris

Pour cela, il faut tout d'abord ... créer une variable oui!Smiley rigole Allez on va prendre un intSmiley souris

         int maVariable = 10;


Pour afficher la valeur de la variable, nous faisons bien ceci:

         printf("%d", maVariable);
 
Et bien pour afficher l'adresse d'une variable, il faut faire comme ceci:

         printf("%p", &maVariable);


Le symbole "%p" a été spécialement concu pour les adresses, donc préférez le aux autres classique "%d", "%lf", etc.. qui fonctionnerons quand mêmeSmiley souris Voici ce que cela affiche chez moi:
 
adresse et pointeur tuto C
 
Cette adresse est bein un nombre, mais écrit en format hexadécimal.

Notez qu'il est tout à fait normal que vous n'ayez pas la même adresse d'affichée que moi et ne vous étonnez pas non plus si elle change une fois le programme relancé! La raison est simple: nous n'avons pas la même quantité de mémoire vive ni la même utilisation de celle ciSmiley souris

Le symbole "&" devant la variable doit vous rappeler quelque chose. En effet, nous l'avons déjà utilisé avec scanf sans trop vous expliquer pourquoiSmiley souris Il est maintenant temps de remédier à celaSmiley rigole

Lorsque le signe "&" est présent devant une variable,
 
cela désigne l'adresse de cette variable et non sa valeur


Nous pouvons donc faire ceci pour mieux faire la différence:


#include <stdlib.h>
#include <stdio.h>


int main()
{
    int maVariable = 10;

    printf("maVariable vaut %d et se situe a l'adresse %p de ma memoire vive.", maVariable, &maVariable);

    return 0;
}
 

Ce qui nous donne:
pointeurs tuto C


Donc il suffit de se rappeler qu'il faut rajouter devant une variable le signe "&" pour donner son adresse.

 
Les pointeurs

Mais qu'est ce dont qu'un pointeur? Nous avons déjà vu de nombreux types de variables (int, char, double, float, etc...).

Et bien en fait, un pointeur n'est rien d'autre qu'une variable dans laquelle est stockée ... une adresse!Smiley rigole Et grâce à cela, on va pouvoir faire plein de zoli' chosesSmiley rigole

Voici comment créer un pointeur: Il suffit de rajouter, collé au nom de la variable une étoile "*" comme ceci:

int *monPointeur = NULL;

L'étoile signifie qu'il s'agit d'un pointeur. Le pointeur peut être de n'importe quel typeSmiley souris

Enfin, on voit que le pointeur est initialisé à NULL (en majuscules!). NULL permet de s'assurer que le pointeur ne contient rien. Il est super-important d'initialiser une variable et d'autant plus un pointeur!


Etant donné qu'un pointeur est créé pour stocker l'adresse d'une variable voici comment lui affecter la valeur de maVariable. Tout simplement:

int maVariable = 10;

int *monPointeur = &maVariable;

Explications:

On créer une variable valant 10. On créer ensuite un pointeur valant l'adresse de maVariable.

Du coup, si on affchiche la variable monPointeur (qui est donc un pointeur) comme une variable classique, il devrait afficher sa valeur et par conséquent ... l'adresse de maVariable!

Essayons:


#include <stdlib.h>
#include <stdio.h>


int main()
{
    int maVariable = 10;

    int *monPointeur = NULL;
    monPointeur = &maVariable;

    printf("monPointeur vaut %p et l'adresse de maVariable est %p", monPointeur, &maVariable);

    return 0;
}
 
Ce qui donne bien:

tuto C pointeurs

 
On vient d'apprendre pas mal de chose là! Mais savez-vous que l'on peut faire encore plus fort?!

En effet, il est possible de gérer une variable grâce à une autre! Et tout cela encore grâce aux pointeurs!Smiley rigole Maintenant, ce que je vais vous expliquer est la chose à retenir des pointeurs. Tenez-vous bien:

On peut, comme nous venons de le voir, créer un pointeur contenant l'adresse d'une variable. Mais l'on peut aussi accéder, grâce à ce pointeur, à la variable se trouvant à cette adresse et par conséquent, la modifier!
 
On dit que le pointeur "monPointeur" pointe sur la variable "maVaiable".
(vocabulaire à retenir).



Pour accéder, à partir d'un pointeur, à la variable que ce dernier pointe, il suffit de mettre l'étoile devant le pointeur.

Voici un exemple:
 
#include <stdlib.h>
#include <stdio.h>


int main()
{
    int maVariable = 10;

    int *monPointeur = NULL;
    monPointeur = &maVariable;

    printf("maVariable vaut %d et monPointeur pointe sur une adresse memoire ou est stocke la valeur %d.", maVariable, *monPointeur);

    return 0;
}
 
Ce qui fait apparaître à l'écran:
 
screen pointeur tuto C


C'est magique! Nous pouvons accéder à une variable juste avec son adresse!
 
Voici un petit mémo de ce qu'il faut impérativement retenir:


maVariable     --> désigne la valeur contenue dans cette variable.
&maVariable   --> désigne l'adresse de cette variable.

monPointeur   --> désigne la valeur contenue dans ce pointeur (c'est donc une adresse).
*monPointeur --> désigne la valeur de la variable pointée par le pointeur.

Si vous maitrisez cela, vous avez tout compris des pointeurs!Smiley rigole Sinon revoyez tout et faîtes des tests. J'ai personnelement mis beaucoup de temps à comprendre le fonctionnement des pointeurs en programmationSmiley souris


Passer un pointeur à une fonction

A partir de là, on va voir le vrai "plus" qu'apportent les pointeurs en programmationSmiley souris

Essayez tout d'abord ce code-ci:


#include <stdlib.h>
#include <stdio.h>


void fonctionIncrementation(int maVariable);

int main()
{
    int maVariable = 39;

    printf("maVariable avant incrementation --> %d  ", maVariable);

    fonctionIncrementation(maVariable);

    printf("maVariable apres incrementation --> %d", maVariable);

    return 0;
}

void fonctionIncrementation(int maVariable)
{
    maVariable += 1;
}

 
Ce qui fait apparaître ceci:
 
passage pointeur fonction tuto C


Mais c'est bizarre! On donne "maVariable" à une fonction qui incrémente la variable et on trouve, à la fin, une nouvelle fois 39!? @_@

La raison en est très simple:

Lorsque vous envoyez une variable en argument à une fonction, celle-ci fait juste une simple copie de cette variable et travaille sur cette copie! En fin de compte, la variable passée en argument n'est jamais modifiée par la fonction ce qui fait qu'elle ne change aucunement de valeur.


Mais maintenant que vous connaissez tous les petits secrets des pointeurs, laissez-moi vous en montrer un dernier: modifier une variable avec une fonction!Smiley rigole


Voici le code qui fonctionne:

#include <stdlib.h>
#include <stdio.h>


void fonctionIncrementation(int *maVariable); //Prototype de la fonction.

int main()
{
    int maVariable = 39; //On créer une variable qui vaut 39.

    printf("maVariable avant incrementation --> %d  ", maVariable); /*On affiche la variable et donc 39.*/

    fonctionIncrementation(&maVariable); //On donne en argument l'adresse de la variable.

    printf("maVariable apres incrementation --> %d", maVariable);

    return 0;
}

//On stocke l'adresse donnée dans un pointeur nommé monPointeur.
void fonctionIncrementation(int *monPointeur)
{
    *monPointeur += 1; //On ajoute 1 à la variable pointée par monPointeur.
}



J'espère que les commentaires rendant plus clair ce codeSmiley souris

Il suffit "juste" de donner l'adresse de la variable à la fonction puis de modifier cette variable directement avec un pointeur. La variable est donc cette fois bien modifiée et n'est plus une simple copie.


De ce fait, vous pouvez même modifier directement plusieurs variables grâce à une fonction sans utiliser de return!Smiley souris


Voilà un nouveau chapitre qui se termine. Un chapitre long mais très important! n'hésitez pas à poser des questions et à relire ce chapitre ainsi qu'à faire des tests!Smiley souris
Le prochain chapitre vous apprendra à créer vos propres types de variables!Smiley rigole


    Les chaines de caractères                                                                    Les structures








 
 
 



Créer un site
Créer un site