Cours programmation : langage C Annexe1 : TDs Chapitre 9 : Les pointeurs Object
Cours programmation : langage C Annexe1 : TDs Chapitre 9 : Les pointeurs Objectifs Connaître la notion de pointeur en C Connaître les caractéristiques des variables de type pointeur en C Savoir écrire des programmes en utilisant les pointeurs 1. Introduction Toute variable manipulée dans un programme est stockée quelque part en mémoire centrale. Cette mémoire est constituée de mots qui sont identifiés de manière univoque par un numéro qu’on appelle adresse. Pour retrouver une variable, il suffit donc de connaître l’adresse du mot où elle est stockée ou (s’il s’agit d’une variable qui recouvre plusieurs mots contigus) l’adresse du premier de ces mots. Pour des raisons évidentes de lisibilité, on désigne souvent les variables par des identificateurs et non par leur adresses. C’est le compilateur qui fait a1.lors le lien entre l’identificateur d’une variable et son adresse en mémoire. Toutefois, il est parfois très pratique de manipuler directement une variable par son adresse. 2. Adresse et valeur d’un objet On appelle Lvalue (Left value) tout objet pouvant être placé à gauche d’un opérateur d’affectation. Une Lvalue est caractérisée par : - son adresse. C’est à dire l’adresse mémoire à partir de laquelle l’objet est stocké. - sa valeur, c’est à dire ce qui est stocké à cette adresse. Adressage direct : Le nom de la variable nous permet d'accéder directement à sa valeur. Adressage direct: Accès au contenu d'une variable par le nom de la variable. Adressage indirect : Si nous ne voulons ou ne pouvons pas utiliser le nom d'une variable A, nous pouvons copier l'adresse de cette variable dans une variable spéciale P, appelée pointeur. Ensuite, nous pouvons retrouver l'information de la variable A en passant par le pointeur P. Adressage indirect: Accès au contenu d'une variable, en passant par un pointeur qui contient l'adresse de la variable. 3. Notion de pointeur Un pointeur est un objet (variable) ‘Lvalue’ dont la valeur est égale à l’adresse d’un autre objet. On déclare un pointeur par l’instruction : Type * nom_du_pointeur ; Type de l’objet pointé Identificateur dont la valeur est l’adresse d’un objet de type Type Cours programmation : langage C Annexe1 : TDs Exemple : char * pc ; /* pc est un pointeur pointant sur un objet de type char */ int * pi ; /* pi est un pointeur pointant sur un objet de type int */ L’opérateur unaire d’indirection * permet d’accéder directement à la valeur de l’objet pointé. Ainsi si p est un pointeur vers un entier i, *p désigne la valeur de i. Par exemple, le programme : main() { int i =3 ; int * p ; /* p est un pointeur sur un objet de type entier */ p = &j ; /* p contient l’adresse de la variable */ printf(« contenu de la case mémoire pointé par p est : %d »,*p) ; } Imprime : contenu de la case mémoire pointé par p est : 3 Dans ce programme, les objets i et *p sont identiques. Ils ont même adresse et valeur. Cela signifie en particulier que toute modification de *p modifie i. Remarque : - La valeur d’un pointeur est toujours un entier. - Le type d’un pointeur dépend du type de la variable à laquelle il pointe 3.1. L'opérateur « adresse de » : & Pour avoir l'adresse mémoire d’une variable, il faudrait utiliser l'opérateur « adresse de » : & Ainsi : &<Nom_Variable> : fournit l’adresse de la variable <Nom_Variable> Exemple: 3.2. L'opérateur « contenu de » : * Pour accéder au contenu de l'adresse mémoire pointée par un pointeur, il faudrait utiliser l'opérateur « contenu de » : * Ainsi : *<Nom_Pointeur> : désigne le contenu de l’adresse référencée par le pointeur <Nom_Pointeur> Exemple: int A = 2; char B; int *p1; char *p2; p1 = &A; /* p1 pointe sur A */ p2 = &B; /* p2 pointe sur B */ int A=10, B=50; int *P; P = &A; /* P pointe sur A */ B = *P; /* B contient 10 */ P = 20; /* A contient 20 */ Cours programmation : langage C Annexe1 : TDs 4. Arithmétique des pointeurs La valeur d’un pointeur étant un entier. On peut lui appliquer un certain nombre d’opérateurs arithmétiques classiques. Les seules opérations arithmétiques valides sur les pointeurs sont : - l’addition d’un entier à un pointeur. Le résultat est un pointeur de même type que le pointeur le départ. - la soustraction d’un entier à un pointeur. Le résultat est un pointeur de même type que le pointeur de départ. - la différence de deux pointeurs p et q pointant tous deux vers des objets de même type. Le résultat est un entier dont la valeur est égale à (p-q)/sizeof(type). NB : Notons que la somme de deux pointeurs n’est pas autorisée. Remarque : Les opérateurs de comparaison sont également applicables aux pointeurs à condition de comparer des pointeurs qui pointent vers des objets de même type. Exemples: 5. Allocation dynamique Lorsque l'on déclare une variable char, int, float .... Un nombre de cases mémoire bien défini est réservé pour cette variable. Il n'en est pas de même avec les pointeurs. Avant de manipuler un pointeur, il faut l’initialiser soit par une allocation dynamique soit par une affectation d’adresse p=&i. Sinon, par défaut la valeur du pointeur est égale à une constante symbolique notée NULL définie dans « stdio.h » En général, cette constante vaut 0. On peut initialiser un pointeur p par une affectation sur p. Mais il faut d’abord réserver à p un espace mémoire de taille adéquate. L’adresse de cet espace mémoire sera la valeur de p. Cette opération consistant à réserver un espace mémoire pour stocker l’objet pointé s’appelle allocation dynamique. Elle se fait en C par la fonction malloc de la librairie standard stdlib.h Sa syntaxe est la suivante : malloc (nombre_cases_mémoire) Cette fonction retourne un pointeur de type char* pointant vers un objet de taille nombre_cases_mémoire. Pour initialiser des pointeurs vers des objets qui ne sont pas de type char*, il faut convertir le type de la sortie de la fonction malloc à l’aide d’un cast. int *pi; /* pi pointe sur un objet de type entier */ float *pr; /* pr pointe sur un objet de type réel */ char *pc; /* pc pointe sur un objet de type caractère */ *pi = 421; / 421 est le contenu de la case mémoire pointée par pi et des 3 suivantes */ *(pi+1) = 53; /*on range 53 4 cases mémoire plus loin */ *pr = 45.7; /*45.7 est rangé dans la case mémoire pointée par pr et les 3 suivantes */ pr++; /* incrémente la valeur du pointeur pr (de 4 cases mémoire) */ *pc = 'j'; /*le contenu de la case mémoire pc est le code ASCII de 'j' */ pc--; / décrémente la valeur du pointeur c (d'une case mémoire) */ Cours programmation : langage C Annexe1 : TDs Exemples : la fonction malloc char * pc ; int * pi, *pj, *pk ; float * pr ; pc = (char*)malloc(10) ; /* on réserve 10 cases mémoire, la place pour 10 caractères */ pi = (int*)malloc(16) ; /* on réserver 16 cases mémoire, soit la place pour 4 entiers */ pr = (float*)malloc(24) ; /* on réserve 24 cases mémoire, soit la place pour 6 réels */ pj = (int*)malloc(sizeof(int)) ; /* on réserve la taille d’un entier en mémoire */ pk = (int*)malloc(3*sizeof(int)) ; /* on réserve la place en mémoire pour 3 entiers */ Remarque1 : Dans l’exemple: main() { int i ; int * p ; p = &i ; } i et *p sont identiques et on n’a pas besoin d’allocation dynamique puisque l’espace mémoire à l’adresse &i est déjà réservé pour un entier. Libération de la mémoire : la fonction free 6. Pointeurs et tableaux 6.1. Pointeur et tableau à une dimension Tout tableau en C est en fait un pointeur constant. Dans la déclaration : int tab[10] ; tab est un pointeur constant non modifiable dont la valeur est l’adresse du premier élément du tableau. Autrement dit tab a pour valeur &tab[0]. On peut donc utiliser un pointeur initialisée à tab pour parcourir les éléments du tableau. Exemple : main() { int tab[5] = {2, 10,5,89,0}; int * p ; p = tab ; /* ou p =&tab[0]; */ for(int i=0; i<5;i++) { printf(“%d\n”, *p); p++;} } 6.2. Tableau de pointeurs La déclaration d’un tableau de pointeur se fait comme suit : Type * NomTableau [N] C’est la déclaration d’un tableau NomTableau de N pointeurs sur des données du type Type. pi = (int*)malloc(16) ; /* on réserve 16 cases mémoire, soit la place pour 4 entiers */ pr = (float*)malloc(24) ; /* on réserve 24 cases mémoire, soit la place pour 6 réels */ free(pi) ; /* on libère la place précédemment réservée pour i */ free(pr) ; /* on libère la place précédemment réservée pour r */ uploads/Litterature/ chapitre-9-les-pointeurs.pdf
Documents similaires










-
31
-
0
-
0
Licence et utilisation
Gratuit pour un usage personnel Attribution requise- Détails
- Publié le Oct 17, 2022
- Catégorie Literature / Litté...
- Langue French
- Taille du fichier 0.3649MB