ADRESSES MÉMOIRE ET POINTEURS
Autant vous dire tout de suite, ça va être dur ! Posez-vous calmement, la concentration totale pour un cerveau est d'environ 15 minutes, faites cette lecture en plusieurs fois, c'est un conseil...
C'est quoi un pointeur ?
Quel nom bizarre ! J'ai déjà entendu parler des pointeurs en prison, mais en informatique, qu'est-ce que ça peut bien être ?
Souvenez-vous ! Une variable contient une valeur, exemple
Code:
int n = 5;
Purée! ça commence, c'est quoi une adresse mémoire ? Pas de stress, vous connaissez votre adresse, celle de votre maison, elle indique l'endroit où vous habitez (j'espère pour vous ) ? Eh bien une adresse mémoire, c'est la même chose, c'est l'endroit en mémoire où va se trouver cette variable.
Une adresse ressemble à une valeur hexadécimale (on s'en fou) du style : 0x7fff46b980a0
Ça sert à quoi un pointeur ?
Son principal objectif, est de modifier la valeur originale contenue dans une variable via une adresse. Travailler avec les adresses mémoires permet aussi de rendre un code bien plus efficace, mais cela est loin d'être notre priorité aujourd'hui...
Est-on obliger d'utiliser les pointeurs?
Oui, et indirectement vous l'utilisez déjà, avec les tableaux de caractères
Attention je n'ai pas dis qu'un tableau de caractères est un pointeur, j'ai juste dis qu'il y a un rapport...
Déclaration d'un pointeur
On utilisera l'opérateur *, juste avant le nom de la variable
Exemple:
Code:
#include <stdio.h> int main(void) { int *p; /* déclaration d'un pointeur dont le nom de variable est p */ /* suite du code */ return 0; }
On va dire que p est une variable pouvant contenir l'adresse mémoire d'une variable de type entier.
Initialisation d'un pointeur
Un pointeur est une variable, elle a donc les mêmes droits qu'une tout autre variable, seulement n'oublions pas, elle contient une adresse... Si on a pas d'adresse contenue dans cette variable on l'exprimera par le terme NULL !
Code:
#include <stdio.h> int main(void) { int *p = NULL; /* déclaration et initialisation de la variable p sans adresse (valeur NULL) */ /* suite du code */ return 0; }
Code:
#include <stdio.h> int main(void) { int *p; /* déclaration de la variable p, contenant adresse d'une variable de type entier */ p = NULL; /* initialisation de la variable p sans adresse (valeur NULL) */ /* suite du code */ return 0; }
Ok, je veux bien créer une variable contenant une adresse mémoire, mais je l'obtiens comment cette adresse ?
On va utiliser un opérateur un peu particulier & qui sera placé à côté de la variable où l'on veut connaître son adresse.
Exemple:
Code:
#include <stdio.h> int main(void) { int n = 2; int *p = &n; /* adresse mémoire de la variable n enregistrée dans la variable p */ /* suite du code */ return 0; }
Comment depuis une adresse mémoire, avoir la valeur de la variable?
Bon vous avez votre adresse mémoire enregistrée dans une variable de type pointeur sur un entier, comment je fais pour avoir la valeur de cette variable ?
On va déréférencer la variable à l'aide de l'opérateur *...
Code:
#include <stdio.h> int main(void) { int n = 2; int *p = &n; int value = *p; /* déréférencement de la variable p pour avoir sa valeur enregistrée dans la variable value */ printf("%d\n", value); /* Affichage valeur de la variable value donc 2 */ return 0; }
Souvenez vous ! Le principal objectif d'un pointeur est de modifier la valeur originale d'une variable via son adresse...
Pour cela on doit
- Assigner l'adresse de la variable à modifier au pointeur
- Déréférencer avec l'opérateur * le pointeur est lui assigner une nouvelle valeur
- Afficher le nouveau contenu de cette variable à modifier
En code ça nous donne cela...
Code:
#include <stdio.h> int main(void) { int n = 2; int *p = &n; /* Assigne l'adresse de n dans p */ *p = 3; /* déréférencement de la variable p et on assigne la nouvelle valeur */ printf("%d\n", n); /* Affichage valeur de la variable n donc 3 */ return 0; }
Code:
#include <stdio.h> int main(void) { int n = 2; int *p = NULL; /* initialise à NULL dans p */ p = &n; /* assigne adresse de n dans p */ *p = 3; /* déréférencement de la variable p et on assigne la nouvelle valeur */ printf("%d\n", n); /* Affichage valeur de la variable n donc 3 */ return 0; }
Évidemment on peut, essayons avec le type char
Code:
#include <stdio.h> int main(void) { char letter = 'A'; char *p = &letter; /* adresse de letter dans p */ *p = 'Z'; /* déréférencement de la variable p et on assigne la nouvelle valeur */ printf("%c\n", letter); /* Affichage valeur de la variable letter donc Z */ return 0; }
Souvenez-vous ! Un tableau de caractères
Plusieurs cases les unes derrière les autres avec comme valeur pour chaque case une lettre.
On imagine donc bien que de pointer sur une adresse d'un tableau va un peu être différent...
Code:
#include <stdio.h> int main(void) { char chaine[] = "Hello"; char *p = &chaine[0]; /* adresse de la 1ère case du tableau chaine dans p */ *p = 'h'; /* déréférencement de la variable p et on assigne la nouvelle valeur 'h' de la 1ère case du tableau chaine */ printf("%s\n", chaine); /* Affichage valeur de la variable chaine donc "hello" */ return 0; }
Code:
#include <stdio.h> int main(void) { char chaine[] = "Hello"; char *p = chaine; /* adresse de la 1ère case du tableau chaine dans p */ *p = 'h'; /* déréférencement de la variable p et on assigne la nouvelle valeur 'h' de la 1ère case du tableau chaine */ printf("%s\n", chaine); /* Affichage valeur de la variable chaine donc "hello" */ return 0; }
Super, je commence à comprendre, je veux faire plus, comment modifier les deux lettres 'l' de "hello" ?
Les deux lettres 'l' se trouvent à la case 2 et 3 du tableau chaine, faisons cette modification, on remplacera 'l' par 'L'
Code:
#include <stdio.h> int main(void) { char chaine[] = "Hello"; char *p = chaine; /* adresse de la 1ère case du tableau chaine dans p */ p += 2; /* je vais à la case mémoire 2 */ *p = 'L'; /* je modifie le 1er 'l' par 'L' */ p += 1; /* je vais à la case mémoire 3 */ *p = 'L'; printf("%s\n", chaine); /* Affichage valeur de la variable chaine donc "HeLLo" */ return 0; }
Eh! Ça vous dit qu'on fasse cela avec une boucle for et while ? Allez c'est parti !
Code:
#include <stdio.h> int main(void) { char chaine[] = "Hello"; char *p = NULL; /* adresse initialisé à NULL dans p */ for (p=chaine; *p!='\0'; p++) /* Pour adresse de chaine[0] à valeur déréférencée de p valant fin de chaine '\0', on incrémente par case mémoire */ { if (*p == 'l') /* on détecte lors du référencement que valeur vaut 'l', valeur à modifier */ { *p = 'L'; /* assignation de la nouvelle valeur 'L' */ } } printf("%s\n", chaine); /* Affichage valeur de la variable chaine donc "HeLLo" */ return 0; }
Avec la boucle while, identique évidemment...
Code:
#include <stdio.h> int main(void) { char chaine[] = "Hello"; char *p = chaine; /* adresse chaine[0] dans p */ while (*p != '\0') /* Tant que la valeur déréférencée de p ne vaut pas la fin de chaine '\0' */ { if (*p == 'l') /* Si valeur déréférencée vaut 'l' */ { *p = 'L'; /* Assigner nouvelle valeur 'L' */ } p++; /* incrémenter de 1 la case mémoire */ } printf("%s\n", chaine); /* Affichage valeur de la variable chaine donc "HeLLo" */ return 0; }
Pas d'exercices, je vous laisse digérer, tester tous ces codes et comprendre. Ça prendra déjà pas mal de temps...
Par contre, le cours suivant sera sur les fonctions, et les pointeurs seront de la fête lors des exercices.
Merci de m'avoir lu et à bientôt pour le prochain cours
Commentaire