Les pointeurs




        Nous abordons ce mois-ci la notion la plus complexe du C mais aussi la plus importante : les pointeurs.
Accrochez-vous c'est parti !


Nous avons déjà un peu utilisé précédemment le principe des pointeurs avec l'operateur d'adressage & qui désigne l'adresse d'un lvalue. Nous allons voir que le C permet de manipuler des adresses mémoires par l'intermédiaire de variables que l'on appelle "pointeur".


Sommaire

1. les opérateurs '&' et '*'
2. les pointeurs et les fonctions
3. Quelques petites remarques


les opérateurs '&' et '*'

        D'une manière générale la déclaration d'un pointeur se fait de cette manière :


<type de la donnée> *<nom de la variable>

        L'opérateur '*' a une tout autre signification que la multiplication, il signifie littéralement ici "est un pointeur vers".


int *pointeur ;


        signifie "la variable "pointeur" pointe vers une donnée de type int".
Le reste du temps '*' devant le nom d'un pointeur désigne le contenu de l'adresse pointée, c'est à dire le contenu d'une variable de type int.
Nous ne reviendrons pas sur l'opérateur '&' qui permet de connaître l'adresse d'une variable.
Voyons plutôt un exemple simple concret :


//déclarer un pointeur pouvant contenir l'adresse d'une variable short
short * pointeur ;
//déclarer une variable de type short
short variable ;
//donner une valeur à la variable
variable = 50 ;
//faire pointer le pointeur sur la variable " variable "
pointeur = &variable ;
//ajouter 30 à la donnée se trouvant à l'adresse contenue
// dans le pointeur (soit celle de la variable "variable")
*pointeur+=30 ;


        Il est à noter que pour la dernière intruction '*pointeur+=30' equivaut donc à 'variable+=30', de même il est important de ne pas confondre l'adresse d'un pointeur (soit son emplacement dans la mémoire de l'ordinateur) et l'adresse pointée par un pointeur (soit le contenu d'un pointeur correspondant généralement à une variable).
Enfin un erreur est souvent commise lorsqu'on manipule les pointeurs. Celle-ci est souvent à l'origne de plantages sérieux de votre OS.


//déclarer un pointeur pouvant contenir l'adresse d'une variable short
short * pointeur ;
//déclarer une variable de type short
short variable ;
//donner une valeur à la variable
variable = 50 ;
//faire pointer le pointeur sur la variable " variable "
pointeur = &variable ;
/*prendre l'adresse du pointeur, l'augmenter de 30,
   se retrouver sur l'adresse d'une variable totalement 
   inconnue que l'on risque de manipuler : ERREUR ! ! !*/
pointeur+=30 ;


        On voit bien ici les conséquences désastreuses que peuvent avoir ce genre d'erreur. Avec des OS peu surs c'est le plantage garanti (qui à dit Windows 9x ? J )




le principe des pointeurs


les pointeurs et les fonctions

        Comme nous l'avons déjà dit une fonction appelée n'a aucun moyen de modifier la variable d'une fonction appellante.
Prenons l'exemple d'une fonction qui échange le contenu de deux variables passés en paramètre par une fonction appellante. Comme le montre le shéma ci-contre ce genre de fonction ne fait rien du tout :


void echanger (int variable1, int variable2)
{
  //créer une variable temporaire pour contenir 
             //le contenu d'une des deux variables à echanger
  int temp ;
  //mettre le contenu de la variable 1 dans la temporaire
  temp = variable1 ;
  //remplacer le contenu de la variable1 par celui de la variable2
  variable1 = variable2 ;
  //donner à variable2 l'ancienne valeur de variable1
  variable2 = temp ;

}
//fin de la fonction toute la mémoire prise par les variables
// a été libérée aucun changement n'a été éffectué


        ici on ne manipule qu'une copie des variables passée en argument par la fonction appellante. Dès que la fonction appelée se termine, les variables créées dans cette fonction disparaissent emportant avec elles les changements. Les variables de la fonction appellante qui devaient être échangées ne le sont donc pas.
Les pointeurs parent ce problème très efficacement :


void echanger (int *pointeur1, int *pointeur2)
{
  //créer une variable temporaire pour contenir
            // le contenu d'une des deux variables à echanger
  int temp ;
  //mettre le contenu de la variable pointée par pointeur1 dans la temporaire
  temp = *pointeur1 ;
  //remplacer le contenu de la variable pointée 
            //par pointeur1 par celui de la variable pointée par pointeur2
  *pointeur1 = *pointeur2 ;
  //donner à pointeur2 l'ancienne valeur de pointeur1
  *pointeur2 = temp ;
}
//fin de la fonction


        La fonction ne manipule plus ici une copie des variables mais bien deux variables dont elle a reçu les adresses par passage d'argument de la fonction appellante.
Elle va donc modifier des variables à une adresse précise et cette adresse se trouve être celle des variables de la fonction appellante. En se finissant la fonction appellée va liberer la mémoire prise par la variable temp et par les pointeurs mais les variables de la fonction appellante ne seront pas touchées et garderont leurs modifications.



les pointeurs et les fonctions


Quelques petites remarques

        Dans la dernière version de la fonction echanger nous n'avons aucune raison de changer les adresses vers lesquelles pointent les pointeurs pointeur1 et pointeur2, nous pourrions donc les mettre en 'const' afin de garantir une certaine securité :


void echanger(int * const pointeur2, int * const pointeur2);

        Ecrire 'int * const a' signifie que le pointeur 'a' pourra désigner une variable possédant différentes valeurs au cours de sa vie mais l'adresse qu'il pointe ne pourra pas changer.
Au contraire, ecrire 'const int * a' signifie que c'est le contenu de la variable pointée par 'a' qui ne pourra pas changer, alors que l'adresse pourrait changer.

        Nous continuerons sur les pointeurs dans notre prochain cours et nous aborderons les structures, l'une des dernières notions qu'il nous reste à apprendre avant la fin des cours sur le langage C


[ Précédent | Index | Suivant ]



par Valentin BILLOTTE
vbillotte@programmationworld.com
http://www.programmationworld.com
Dernière mise à jour: