pointeurs

Embed Size (px)

Citation preview

  • 8/3/2019 pointeurs

    1/6

    Les pointeurs Formation langage C - 1re Anne 18/01/00

    1

    Principe et usage des pointeurs en langage C

    1. Adressage de la mmoire de lordinateur

    Lorsque lon lance lexcution dun programme, toutes les instructions de ce programme et ses donnes sontcharges dans la mmoire de l'ordinateur. De faon trs approximative, on peut considrer cette dernire comme

    une suite de cases, chacune de ces cases pouvant contenir une variable. Chacune de ces cases a un numro

    dordre (adresse) dans la mmoire de lordinateur et un contenu (valeur de la variable).

    Soit le programme suivant :

    main demo(){

    char premier=a,

    ..

    Une vue partielle de la mmoire au lancement de ce programme donnerait ("approximativement")

    Adresse case mmoire Contenu case mmoire Nom variable stocke

    Case 0 peu importe ! .peu importe !

    Case 1

    ..

    Case 10345 a .premier

    2. Dfinition dun pointeurUne variable de type pointeur est une variable qui contient l'adresse mmoire o est stocke une autre

    variable.Par exemple en reprenant l'exemple prcdent et en supposant que la variablepanneau est un pointeur qui

    pointe vers la variablepremieron aurait:

    Adresse case mmoire Contenu case mmoire Nom variable stocke

    Case 0 peu importe ! .peu importe !

    Case 1

    ..

    Case 10345 a .premier

    Case 108945 10345 .panneau

    panneau contient l'adresse laquelle est stocke la variablepremier, c'est donc est un pointeur vers premier.

    3. Dclaration dun pointeur

    On dclare une variable de type pointeur en prcisant vers quel type de variable elle pointe, et en la prcdent

    par * ; ainsi par exemple:

    char * verschar; verschar est une variable pointeur vers une variable de type char

    int * versint; ; versint est une variable pointeur vers une variable de type int

    float *versfloat; versfloat est une variable pointeur vers une variable de type floatFILE * versfile; versfile est une variable pointeur vers un descripteur de fichier

    int (* versfonc) (int, float); versfonc est une variable pointeur vers une fonction retournant un entier et

    ayant pour paramtres une variable entire et une variable de type float

  • 8/3/2019 pointeurs

    2/6

    Les pointeurs Formation langage C - 1re Anne 18/01/00

    2

    4. Oprateur & et * , initialisation d'un pointeur

    Un pointeur, pour pouvoir tre utilis, doit tre initialis (juste aprs sa dclaration le pointeur contient une

    adresse alatoire c'est dire pointant vers une adresse invalide).

    Pour obtenir l'adresse de la variable vers laquelle on doit pointer on peut utiliser l'oprateur &

    Ainsi l'exemple ci dessous:

    main(){

    int aaa=0; /* la variable entire aaa est dclare */

    int * versint; /* la variable versint est dclare comme pointeur vers un entier, et contientinitialement une valeur alatoire */

    aaa=5; /* aaa est initialise la valeur 5 */

    versint=&aaaa; /* l'adresse de la variable aaa est mise dans versint qui est maintenant un pointeur

    valide */

    Reprenons l'exemple ci-dessous en dtaillant l'tat de la mmoire diffrentes tapes:

    Etape 1: le programme est charg en mmoire et n'a pas commenc son excution

    Adresse case mmoire Contenu case mmoire Nom variable stocke

    Case 0 peu importe ! .peu importe !

    Case 1

    ..

    Case 078960 0 .aaa

    Case 089000 VALEUR ALEATOIRE .versint

    Contenu de la mmoire aprs excution de la ligne aaa=5 ;

    Adresse case mmoire Contenu case mmoire Nom variable stocke

    Case 0 peu importe ! .peu importe !

    Case 1

    ..

    Case 078960 5 .aaa

    Case 089000 VALEUR ALEATOIRE .versint

    Contenu de la mmoire aprs excution de la ligne versint=&aaa;

    Adresse case mmoire Contenu case mmoire Nom variable stocke

    Case 0 peu importe ! .peu importe !

    Case 1

    ..

    Case 078960 5 .aaar

    Case 089000 078960 .versint

    L'oprateur * mis devant un pointeur permet d'obtenir le contenu de la variable pointe par lepointeur; ainsi aprs excution du code prcdent, un printf("%d",*verint) afficherait 5

  • 8/3/2019 pointeurs

    3/6

    Les pointeurs Formation langage C - 1re Anne 18/01/00

    3

    Autre exemple:

    main(){

    int aaa,bbb; /* les variables entire aaa et bbb sont dclares */

    int * versint; /* la variable versint est dclare comme pointeur vers un entier, et contientinitialement une valeur alatoire */

    aaa=5; /* aaa est initialise la valeur 5 */versint=&aaaa; /* l'adresse de la variable aaa est mise dans versint qui est maintenant un pointeur

    valide */

    bbb=*versint; /* bbb prend pour valeur le contenu de la variable pointe par versint c.a.d la valeurcontenue dans aaa */

    Exemples dutilisation

    1. Utilisation dans les procdures

    En C, il est ncessaire de programmer de faon modulaire en utilisant des procdures,;

    Voici un exemple d'utilisation de procdure:

    void increment(int bbb) {

    bbb=bbb+1;

    printf("\n bbb vaut %d\n",bbb);

    return;

    }

    main(){

    int aaa; /* la variable entire aaa est dclare */

    aaa=5; /* aaa est initialise la valeur 5 */increment(aaa); /* appel de incrment avec la variable aaa comme paramtre */

    printf("%d",aaa); /* affichage de la valeur contenue dans aaa donc 5 */}

    Droulons l'excution du programme:

    aaa est initialise 5 appel increment en lui "passant" aaa comme paramtre le contenu de aaa est recopi dans le variable bbb locale la procdure increment bbb est incrment de 1 on sort de la procdure increment on affiche le contenu de aaa qui vaut 5

    Chaque fois que l'on appelle une procdure, les paramtres passs la procdure au moment de l'appel sont

    recopis dans des variables locales la procdure (on parle de passage de paramtres par valeur)

  • 8/3/2019 pointeurs

    4/6

    Les pointeurs Formation langage C - 1re Anne 18/01/00

    4

    Pour pouvoir modifier la variable aaa depuis la procdure, il faut passer l'adresse de aaa la procdure en

    paramtre, adresse qui sera recopie dans une variable pointeur locale la procdure incrment; le programme

    devient alors:

    void increment(int* bbb) { /* la variable bbb est un pointeur vers un entier */

    *bbb=*bbb+1; /* le contenu de la variable pointe par bbb est incrment de 1 */

    printf("\n bbb pointe vers une variable entiere contenant %d\n",*bbb);return;

    }

    main(){

    int aaa; /* la variable entire aaa est dclare */

    aaa=5; /*la variable aaa est initialise la valeur 5 */

    increment(&aaa); /* appel de incrment avec l'adresse de la variable aaa comme paramtre*/

    printf("%d",aaa); /* la variable aaa contient maintenant 6 */

    }

    Droulons l'excution du programme:

    aaa est initialise 5 appel increment en lui "passant" l'adresse de aaa comme paramtre (&aaa), l'adresse de aaa est recopie dans le pointeur vers entier bbb local la procdure increment, la variable dont l'adresse est contenu dans bbb est incrment de 1 (*bbb=*bbb+1)

    (donc le contenu de la variable aaa est incrment de 1)

    on sort de la procdure increment, on affiche le contenu de aaa qui vaut maintenant 6

    NB: Ceci explique que lorsqu'on utilise la procdure scanf pour initialiser le contenu de variables, toutesles variables passes scanf doivent tre prcdes par & (i.e. on passe l'adresse des variables initialiseravec les valeurs saisies par l'utilisateur)

    2. Utilisation dans les tableaux

    En C, on peut dfinir des tableaux; ces tableaux sont stocks comme une suite de variable du mme type;

    Ainsi la dclaration d'un tableau de 100 entiers:

    int montableau[100];

    Ces 100 entiers sont stocks de manire conscutives, on peut utiliser un pointeur pour parcourir ce tableau

    Soit le code:

    int i,montableau[100];

    int * versint;

    versint=&montableau[0];for (i=0;i

  • 8/3/2019 pointeurs

    5/6

    Les pointeurs Formation langage C - 1re Anne 18/01/00

    5

    3. Allocation de mmoire dynamique

    Un des problmes du C est que l'allocation des tableaux est statique (on doit connatre la taille maximum du

    tableau au moment de la compilation). Pour contourner ce problme, il est possible de demander au systme

    de nous allouer une portion de la mmoire, le systme nous rendant un pointeur vers cette zone.

    On utilise pour cela la fonction malloc qui prend comme paramtre la taille en octets de la zone mmoiresouhaite . Par exemple pour s'allouer une zone de 100 entiers

    int * mazone; /* dclaration d'un pointeur vers entier */

    mazone=(int* ) malloc(100*sizeof(int)); /* sizeof(int) donne la taille en octets d'une variable de

    type int ; (*int) convertit le pointeur vers void retournpar malloc en pointeur vers un entier; mazone contient

    maintenant un pointeur vers une zone mmoire suffisante

    pour stocker 100 entiers et pas un de plus */

    Il est noter que malloc retourne un pointeur vers void ; pour pouvoir mettre l'adresse retourne dans un

    pointeur vers un entier, il faut convertir (en anglais "cast") l'adresse retourne par malloc en pointeur vers unentier ceci est ralis dans le code ci-dessus par l'opration (int *)

    Pour initialiser ces 100 entiers, on pourrait modifier le programme comme ci-aprs:

    int * mazone,i;

    mazone=(int* ) malloc(100*sizeof(int)); /*allocation d'une zone de stockage pour 100 entiers */for (i=0;i

  • 8/3/2019 pointeurs

    6/6

    Les pointeurs Formation langage C - 1re Anne 18/01/00

    6

    Problmes frquemment rencontrs avec les pointeurs

    1. Core dump ou segmentation fault

    Lorsqu'un programme se plante en gnrant un "core dump" (cration d'un fichier core contenant l'image de lammoire utilise par le programme au moment o il s'est plant), c'est gnralement parce que l'on a utilis un

    pointeur incorrectement initialis

    Le top 3 des erreurs induisant un core dump :

    oublier le & devant les variables passes comme paramtres scanf utiliser un pointeur pour stocker/accder des donnesavant d'avoir initialis le pointeur

    (l'initialisation du pointeur est effectue en y mettant soit l'adresse d'une variable djexistante, soit l'adresse d'une zone alloue par malloc)

    essayer de mettre plus de donnes dans la zone alloue que prvu initialement (stockage du 101meentier dans une zone alloue par malloc pour 100 entiers)

    Pour dpanner il suffit au choix :

    De regarder attentivement son code (ventuellement rajout de printf pour savoir o on en est au moment du"core dump")

    Ou bien

    De compiler avec l'option de debuggage (-g), de rexcuter votre programme pour rgnrer un fichiercore; puis de lancer le debuggeur;

    Avec xxgdb utiliser la commande bt (a donnera la ligne o le programme s'estplant)

    Avec ddd utiliser le menu status->backtrace