mardi 9 septembre 2008

Les pointeurs en C

Les pointeurs !! c' est quelque chose qui fait fuire beaucoup de débutant en langage C et pourtant c' est simple comme bonjour... quand on a compris le principe.
C' est ce que je vais essayer de faire avec des exemples pratique, donc pas de théorie ou très peu.
Alors un pointeur est une variable qui peut contenir l' adresse d' une autre variable (du même type).

en faisant *pointeur j' obtiens la valeur de l' adresse pointer par pointeur.
en faisant &pointeur j' obtient l' adresse de pointeur.
c' est comme pour une variable normal.

Mais vérifions tout de suite ce que j' avance :

char *p;
printf("[ adresse de p: %p adresse pointer par p: %p ]\n", &p, p);


L' execution de ce bout de code me donne :

[ adresse de p: 0xbffb5d28 adresse pointer par p: 0xbffb5d48 ]


La vous allez me dire mais le pointeur ne pointe sur rien du tout et pourtant il contient une adresse c' est normal ?
Oui en effet, je n' ai pas initialiser le pointeur a NULL, donc il pointe n' importe ou en mémoire, donc voila l' importance d' initialiser ses pointeur a NULL.

On recommence de la bonne façon cette fois :

char *p = NULL;
printf("[ adresse de p: %p adresse pointer par p: %p ]\n", &p, p);


L' execution de ce bout de code me donne :

[ adresse de p: 0xbffa9d28 adresse pointer par p: (nil) ]


La ok il pointe nul part et est bien initialiser a NULL.

Maintenant on sais initialiser comme il faut un pointeur mais on sais autre chose, on sais que si on veut que notre pointeur pointe sur l' adresse d' une variable on va devoir remplacer (nil) qui est rien d autre qu une case pour stocker une adresse, par l' adresse de la variable sur laquelle on veut pointer non ?

donc c' est simple :

char caractere = 'B';
char *p = NULL;

printf("[ adresse de caractere : %p | contenu de caractere: %c ]\n\n", &caractere, caractere);

printf("[ adresse de p : %p -> adresse pointer par p: %p ]\n\n", &p, p);

puts("Maintenant on remplace (nil) par l adresse de caractere\n");

p = &caractere;

printf("[ adresse de p : %p -> adresse pointer par p: %p ]\n", &p, p);

printf("[ adresse de p: %p | contenu de l' adresse pointer par p: %c ]\n", &p, *p);


L' execution donne:

[ adresse de caractere : 0xbfcd4253 | contenu de caractere: B ]

[ adresse de p : 0xbfcd424c -> adresse pointer par p: (nil) ]

Maintenant on remplace (nil) par l adresse de caractere

[ adresse de p : 0xbfcd424c -> adresse pointer par p: 0xbfcd4253 ]

[ adresse de p: 0xbfcd424c | contenu de l' adresse pointer par p: B ]


Vous voyez que les adresses en rouge sont les mêmes, donc on bien réussi a faire pointer q sur l adresse de caractere.J' aurais pu faire l impasse sur l adresse du pointeur (qui est toujour la meme elle ne change pas) mais c' est justement pour bien comprendre qu' un pointeur est exactement comme une variable sauf que a la place de contenir une valeur, elle contient l adresse d' une valeur.

On va appronfondir cette histoire de signe afin de bien comprendre avec un exemple simple:

rapel :
en faisant *pointeur j' obtiens la valeur de l' adresse pointer par pointeur.
en faisant &pointeur j' obtient l' adresse de pointeur.
donc voici un bout de code tout a fait valide et qui va permettre de comprendre encore mieux cette histoire de signe.

char caractere = 'B';

printf("caractere: %c\n", caractere);

*(&caractere) = 'C';

printf("caractere: %c\n", *(&caractere) );


et oui *(&caractere) est bien equivalent a caractere.

met moi la lettre C dans le contenu *() de l' adresse de &caractere.

Pour finir voila un bout de code que vous ne devriez plus avoir aucun mal a comprendre, j' ai mis des couleurs pour aider:
char caractere = 'B';
char *p = NULL;
char **p_p = NULL;
p = &caractere;
p_p = &p;

printf("[ adresse de caractere: %p | valeur: %c ]\n\n", &caractere, caractere);
printf("[ adresse de p: %p | adresse pointer par p: %p ]\n\n", &p, p);
printf("[ adresse de p_p: %p | adresse pointer par p_p: %p ]\n\n", &p_p, p_p);

printf("valeur de caractere : %c\n", caractere);
printf("valeur de p : %c\n", *p);
printf("valeur de p_p : %c\n", **p_p);


L' execution de ce code donne:

[ adresse de caractere: 0xbf94aed3 | valeur: B ]

[ adresse de p: 0xbf94aecc | adresse pointer par p: 0xbf94aed3 ]

[ adresse de p_p: 0xbf94aec8 | adresse pointer par p_p: 0xbf94aecc ]

valeur de caractere : B
valeur de p : B
valeur de p_p : B

Aucun commentaire: