Pointeurs
Accueil

du site

La notion de pointeur est d'une importance primordiale dans ce langage.
On ne peut pas aller très loin si on ne l'a pas clairement comprise.
Or, des générations d'étudiants vous diront avoir eu du mal à la saisir rapidement.
Aussi vais-je m'efforcer de l'expliquer du mieux possible.

Pour comprendre la notion de pointeur en langage C, il faut avoir à l'esprit la manière dont votre ordinateur organise et accède à la mémoire.

Nous présentons ci-dessous le schéma d'une mémoire organisée comme une suite d'octets numérotés par des nombres de 16 bits appelés adresses. On peut parler de l'adresse d'un octet.

Ainsi, les adresses s'étendent de 0 à 216 = 65 535. Soit, en hexadécimal de 0 à FFFF.
On fait plus volumineux aujourd'hui, mais le principe reste le même.

La figure ci-dessus montre le contenu de quelques octets de la mémoire :
A l'adresse FA71 écrite en hexadécimal, vous trouvez le code binaire de la lettre 'S'
Ce code que nous avons écrit sous la forme 'S' pourrait s'écrire 53 en hexadécimal, 01010011 en bianire, et 83 en décimal, mais nous avons trouvé 'S' plus pratique icii.
Le mot "SALUT" est manifestement écrit sur 5 octets couvrant l'étendue mémoire de l'adresse FA71 à l'adrese FA75.
L'adresse FA76 pointe sur un octet dont la valeur binaire est 00000000.
Comme nous le verrons plus tard, le langage C se sert de cette valeur nulle pour indiquer qu'une chaîne de caractères est terminée.
Zéro est le terminateur de chaîne pour le langage C.
Les autres emplacements de la mémoire contiennent d'autres valeurs binaires pouvant représenter n'importe quel type de variable ou de constante.

Pour la lettre 'S' du mot salut on peut s'exprimer de deux manières :

  1. Sa valeur binaire 'S' = 01010011 occupe l'emplacement d'adresse FA71.
  2. Le contenu de l'adresse FA71 est 'S' = 01010011

Ainsi, un objet informatique enregistré en mémoire sera désormais caractérisé :

Tous ce éléments étant liés entre eux.

POINTEURS - Référencement -

En fait, c'est très simple :
Si vous voulez parfaitement localiser un objet en mémoire, vous devez connaître l'adresse du pemier octet de cet objet stocké en mémoire et l'étendue en octets de l'objet : son type en somme.

Un pointeur est précisément un objet qui contient les deux informations suivantes :

  • l'adresse du premier emplacement occupé en mémoire par l'objet pointé
  • plus le type de l'objet pointé.

Ainsi, lorsque nous déclarons une variable x de type flottant (4 octets) ,
et que nous lui affectons la valeur 3.12 :
float x = 3.12 ;

Le compilateur enregistre automatiquement cette valeur en mémoire sur 4 octets à partir d'une adresse qu'il choisit lui-même en fonction des disponibilités : mettons 3EB8 pour fixer les idées.
(en fait nous ne nous intéresserons jamais à la valeur numérique de cette adresse et il est même difficile de la connaître dans la plupart des cas).

Le pointeur sur x se note "&x", il contient :

  • l'adresse 3EB8
  • le type float : 4
Le pointeur sur une variable
s'obtient en faisant précéder cette variable
du signe 'et commercial' : &
Exemple : &v est un pointeur sur v
Il n'est pas nécesaire de coller le '&' à la variable.
Même règle pour une constante déclarée par "const"

Le fait d'obtenir le pointeur d'une variable ou constante "const" , s'appelle le référencement de cette variable.
Le signe & est l'opérateur de référencement d'un variable ou constante" const"

Le pointeur &v est une constante puisque l'adresse de stockage d'une variable est définitivement attribuée par le compilateur et ne peut plus être ultérieurement modifiée.
La suite montrera qu'on peut créer des pointeurs variables, disons des variables de type pointeur

Pointeurs pointant d'autres pointeurs :
Remarquez également que rien ne s'oppose à ce que le contenu d'un pointeur puisse être à son tour enregistré en mémoire.
C'est le cas du pointeur du bas de la figure précédente, pointant sur l'adresse FA71 et de type - 2 octets,
peuvent être enregistrés dans une autre zone de mémoire. Ici pointée par une autre pointeur sur FA7D.

On peut d'ailleurs répéter cette opération autant de fois que capacité de la mémoire le permet.

En fait, comme nous le verrons plus tard, cette opération n'est par une vue de l'esprit : elle rend d'irremplaçables services.


MANIPULER LES POINTEURS - Déréférencement -


Déclaration d'une variable pointeur :

Quelques exemples :

int *pEntier ; // L'identificateur "pEntier" est déclaré comme pointeur d'entier
char *pCarac ; // pCarac est déclaré comme pointeur de caractère
float *pPression, * ptrTemperature, Temperature, Pression ;
//
La ligne précédente déclare deux pointeurs de flottant : pPression & ptrTemperature
// et deux flottants Temperature et Pression

Remarques :

  • Notez que les lettres p ou ptr devant pPression et ptrTemperature ne jouent aucun rôle dans la déclaration d'un pointeur si ce n'est de permettre d'en faciliter la reconnaissance visuelle.
    Ceci suppose une convention tacite entre le programmeur et les lecteurs des codes source.
    Cette convention n'est nullement obligatoire.
  • Le fait qu'une variable s'appelle Pression et qu'un pointeur s'appelle pPression, n'implique nullement que pPression pointe sur Pression


Affectation d'une valeur à un pointeur :

Attention :
Toute variable déclarée mais à laquelle on n'a pas encore affecté de valeur a une valeur indeterminée.
C'est aussi le cas d'un pointeur qui vient d'être déclaré.
Cet état de fait est dangereux pour un pointeur car il pointe n'importe où dans la mémoire.
Si on l'utilise tel quel, des emplacement de la mémoire peuvent être modifiés et graves dysfonctionnements peuvent se produire.
Les compilateurs évolués signalent la présence de variables pointeurs non initialisés.

Exemple d'utilisation correcte d'un pointeur déclaré :

double Vitesse;
double * pVitesse;
pVitesse = &Vitesse;
// déclaration de la variable "Vitesse"
// déclaration d'un pointeur "pVitesse" sur une variable de type double
// afféctation de la valeur du pointeur sur "Vitesse" au pointeur "pVitesse"

les pointeurs pVitesse et &Vitesse pointent désormais sur la même variable : Vitesse

(encore une fois, la lettre p de pVitesse et le fait que le pointeur et la variable contiennent le mot Vitesse, n'ont rien à voir avec le mécanisme de déclaration, cela facilite seulement la lecture)

 


Contenu de la variable pointée par un pointeur :

Si P est un pointeur sur la variable V,
*P et V désignent tous deux le même contenu,
*P égale V.

Cette opération s'appelle le déréférencement du pointeur
*
est l'opérateur de déréférencement.

A ce titre, l'étoile * peut se lire : "valeur ou contenu de la variable pointée par"

//Exemple.c

#include <stdio.h>

int main()
{
float Vitesse, *pVitesse;
pVitesse = & Vitesse;

Vitesse = 80.5;

printf("Vitesse en km par h : %f", Vitesse);
printf("Vitesse en km par h : %f",*pVitesse);

}

Commentaires :
Nous rappelons que "printf(...)" est une fonction d'affichage sur l'écran.
Le signe "pour cent" % indique la place à laquelle doit s'afficher la variable dans la phrase affichée.
La lettre "f" de "%f" indique que la variable sera affichée sous type flottant.
Le signe "\n" indique qu'il faut aller à la ligne.
Définition complète de la fonction "printf" en "Fonctions d'affichage".

Après compilation et lancement, affichage obtenu :

Vitesse en km par h : 80.5000000
Vitesse en km par h : 80.5000000


Utilisation d'un pointeur pour modifier la valeur d'une variable :

//Exemple.c

#include <stdio.h>

int main()
{
float Vitesse, *pVitesse;
pVitesse = & Vitesse;

Vitesse = 80.5;
printf("Vitesse en km par h : %f", Vitesse);
printf("Vitesse en km par h : %f",*pVitesse);

Vitesse = 100.75;
printf("Vitesse en km par h : %f", Vitesse);
printf("Vitesse en km par h : %f",*pVitesse);

*pVitesse = 200.30; =
printf("Vitesse en km par h : %f", Vitesse);
printf("Vitesse en km par h : %f",*pVitesse);

}


Affichage :

Vitesse en km par h : 80.5000000
Vitesse en km par h : 80.5000000
Vitesse en km par h : 100.750000
Vitesse en km par h : 100.750000
Vitesse en km par h : 200.300000
Vitesse en km par h : 200.300000


Cet exemple montre que la variable peur être modifiée soit directement par son identifiant, soit indirectement par un pointeur pointé sur elle.

La suite va vous monter que le fait de pouvoir modifier ou lire une variable par l'intermédiaire d'un pointeur
est l'une de plus importantes fonctionnalités du langage.


Suite logique : "Les Tableaux"

Exemples de programmation sur les pointeurs

Sommaire cours C - C++

Accueil

du site