les pointeurs manipulation d'adresses et de ce qui est contenu dans ces adresses très...

67
Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre', 'difficile à utiliser', 'écriture impossible à interpréter' comprendre ce qu'est une adresse emploi quasi naturel des pointeurs et des notations associées Les pointeurs sont un outil puissant !

Upload: thierry-salle

Post on 03-Apr-2015

116 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les pointeurs

Manipulation d'adresses et de ce qui est contenu dans ces adresses

Très important, fondamental même en C

mauvaise réputation : 'dur à comprendre', 'difficile à utiliser', 'écriture impossible à interpréter'

comprendre ce qu'est une adresse emploi quasi naturel des pointeurs et des notations associées

Les pointeurs sont un outil puissant !

Page 2: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

Retour sur les variables :

4 caractéristiques :

• un type

• un nom

• une valeur

• une adresse

les 3 premières déjà bien exploitées. Mais la 4ème ?

Page 3: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

Schématisation par une boîte ou cellule :

l'ordinateur doit stocker cette variable quelque part : dans la RAM

les octets (ou cellules) de la RAM sont numérotés pour que la machine s'y retrouve : chaque cellule à une adresse, et peut contenir une valeur (son contenu)

Attention à la distinction adresse/contenu

Page 4: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

Schématisation de la mémoire :

Cellules consécutives

adresse

contenus

nn+1n+2n+3n+4n+5n+6

Page 5: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

Les adresses démarrent à 0.

Lors de la déclaration de variable, le compilateur associe automatiquement une adresse à la variable inconnue du programmeur.

Le programmeur connaît juste le nom de la variable.

a chaque fois que le compilateur rencontre le nom : il en déduit l'adresse.

Possède une table de correspondance : nom de variable adresse de cette variable en mémoire.

Page 6: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Illustration par un petit programme

void main(){

int val1,val2;

val1 = 3;val2 = -2*val1+4;

if (val2 < val1){printf("%d < %d\n",val2,val1);}

}

Les adresses

Le compilateur utilise des cellules en mémoire pour stocker ces valeurs. Il les 'alloue'.

Exemple : val1 à l'adresse 1000, val2 à l'adresse 1001 (arbitraire)

Page 7: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

1000100110021003100410051006

Lorsque l'on utilise val1, la machine va consulter l'adresse 1000

Valeur stockée dans val1

Valeur stockée dans val2

Lorsque l'on utilise val2, la machine va consulter l'adresse 1001

Invisible pour le programmeur ou l'utilisateur

Page 8: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

void main(){

int val1,val2;

val1 = 3;val2 = -2*val1+4;

if (val2 < val1){printf("%d < %d\n",val2,val1);}

}

Les adresses

Le nom de la variable "masque" son adresse

Le compilateur utilise sa table de correspondance : val1 adresse 1000

Page 9: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

1000100110021003100410051006

Effet de l'instruction val1 = 3; en mémoire

3Valeur stockée dans val2

Page 10: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

void main(){

int val1,val2;

val1 = 3;val2 = -2*val1+4;

if (val2 < val1){printf("%d < %d\n",val2,val1);}

}

Les adresses

Le compilateur utilise sa table de correspondance pour val1 et val2

Page 11: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

1000100110021003100410051006

Effet de l'instruction val2 = -2*val1+4; en mémoire

3

-2

Page 12: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

On peut parfois avoir besoin de manipuler l'adresse d'une variable :

on peut y accéder en utilisant l'opérateur & (prise d'adresse) devant le nom de la variable.

&nom_de_variable se lit : adresse de la variable nom_de_variable.

Sur l'exemple précédent, après la déclaration de variable :

val1 n'est pas initialisée (on ne connaît pas la valeur stockée à l'adresse correspondante, donnée par le compilateur)

&val1 vaut 1000 : c'est l'adresse de val1

Page 13: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

Une variable sera représentée par une boîte au dessus de laquelle est notée son nom, et qui contient sa valeur.

Exemple :

On symbolisera systématiquement une adresse par une flèche, pour indiquer que c'est le moyen utilisé pour trouver une variable dans la mémoire.

val1

val1

Représente la variable val1

Représente l'adresse de val1

&val1

Page 14: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les adresses

On peut aussi voir cette flèche comme un panneau indicateur que l'on peut consulter.

Val1: adresse 1000

Représente &val1

Page 15: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les pointeurs

Les pointeurs sont des variables qui contiennent de tels panneaux ou flèches.

La valeur que contient une variable de type pointeur est une adresse (d'une variable par exemple).

Comme toute variable, on les symbolise par une boîte, mais cette boîte contient une flèche et non une valeur entière ou à virgule.

Soit ptr une variable de type pointeur (nous verrons la syntaxe de déclaration et d'utilisation plus tard). On la représente ainsi :

ptr

Page 16: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les pointeurs

Les pointeurs sont des variables qui contiennent de tels panneaux ou flèches.

La valeur que contient une variable de type pointeur est une adresse (d'une variable par exemple).

Comme toute variable, on les symbolise par une boîte, mais cette boîte contient une flèche et non une valeur entière ou à virgule.

Soit ptr une variable de type pointeur (nous verrons la syntaxe de déclaration et d'utilisation plus tard). On le représente ainsi :

ptr

Page 17: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

La prise de contenu

Raisonnement inverse :

on dispose de l'opérateur *, qui placé devant un pointeur, permet d'accéder à la valeur contenue en mémoire à cette adresse

ne pas confondre avec la multiplication, qui a 2 opérandes

si ptr est un pointeur, alors *ptr est la valeur contenue en mémoire à l'adresse que contient ptr.

*ptr se lit : contenu de ptr.

Page 18: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Les pointeurs : illustration

1000100110021003100410051006

3

15

0

-845

6311

ptr

1002

Si ptr vaut 1002 :

*ptr est ce qui est contenu à l'adresse 1002 : 0

Page 19: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs et types pointés

Lors de la prise de contenu : combien de cellules (ou d'octets) lire ?

Si c'est un char : 1 octet; int : 2 ou 4 octets; float : 4 octets

on doit connaître le type du contenu.

Un pointeur désigne un contenu typé :

pointeur sur char;

pointeur sur int;

pointeur sur float;

etc...

Type pointé précisé lors de la déclaration.

Page 20: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Déclaration

Syntaxe : prête à confusion

pointeur défini par le type du contenu qu'il pointe

exemple : déclarer une variable ptr comme un pointeur sur int déclarer une variable ptr dont le contenu est de type int.

D'où la déclaration :

int *ptr;

se lit : le contenu de ptr (*ptr) est de type int

par abus de langage : ptr est un pointeur sur int;

toujours lire * comme 'contenu' !

Page 21: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Programme exemple suivant : version 1

illustration avec boîtes et flèches

#include <stdio.h>

void main(){

short int var1;short int *ptr;

var1 = 43; /* correct */*ptr = 5; /* provoquera une erreur */

}

var1

ptr

Page 22: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Programme exemple suivant : version 1

effet des instructions

#include <stdio.h>

void main(){

short int var1;short int *ptr;

var1 = 43; /* correct */*ptr = 5; /* provoquera une erreur */

}

var1

ptr

43

Page 23: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

ptr est juste le panneau (flèche), il ne pointe pas un endroit précis dans la mémoire

?

ptr

Page 24: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

*ptr n'est pas défini : si l'on suit le panneau, on va n'importe où : erreur lors de l'exécution du programme.

Ajoutons la ligne suivante, entre var1=43; et *ptr=5;

ptr = &var1;

détail de cette ligne avec boîtes et flèches :ptr

var1&var1

Égalité entres les flèches

43

Page 25: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

ptr

var1

Var1: qqpart

Ou encore :

ptr

43

Page 26: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

ptr

var1

43

Maintenant, ptr pointe sur var1, le panneau indique une destination

que fait la ligne suivante : *ptr=5; ?

ptr

var1

Avant cette ligne :

Après cette ligne :

À vous de jouer

Page 27: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Reprise de l'exemple avec le schéma de la mémoire :

short int var1;short int *ptr;

var1 = 43; ptr=&var1;*ptr = 5;

Effet : 2 octets utilisés pour stocker un short int.

nn+1n+2n+3n+4n+5n+6

?

Page 28: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Reprise de l'exemple avec le schéma de la mémoire :

short int var1;short int *ptr;

var1 = 43; ptr=&var1;*ptr = 5;

Effet : 4 octets utilisés pour stocker un pointeur vers un short int.

nn+1n+2n+3n+4n+5n+6

?

?

Page 29: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Reprise de l'exemple avec le schéma de la mémoire :

short int var1;short int *ptr;

var1 = 43; ptr=&var1;*ptr = 5;

Effet : stocker 43 dans var1.

nn+1n+2n+3n+4n+5n+6

?

43

Page 30: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Reprise de l'exemple avec le schéma de la mémoire :

short int var1;short int *ptr;

var1 = 43; ptr=&var1;*ptr = 5;

Effet : fait pointer ptr sur var1.

nn+1n+2n+3n+4n+5n+6

43

&var1

Page 31: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

État du pointeur après déclaration

Reprise de l'exemple avec le schéma de la mémoire :

short int var1;short int *ptr;

var1 = 43; ptr=&var1;*ptr = 5;

Effet : stocke 5 dans le contenu de ptr.

nn+1n+2n+3n+4n+5n+6

5

&var1

Page 32: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

ManipulationsQue font les programmes suivants ? Donner une illustration.

#include <stdio.h>

void main(){

char a,b;char *p_ch;

a=18;p_ch=&b;*p_ch=a;b=b+1;a=b;*p_ch=119;

}

Page 33: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

ManipulationsQue font les programmes suivants ? Donner une illustration.

#include <stdio.h>

void main(){

float x_1,y_1;float *p_fl;

x_1=3.14159;p_fl=&x_1;y_1 = 2.0*(*p_fl)*5.0;*p_fl= y_1 - x_1;

}

Page 34: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

ManipulationsSoient les instructions suivantes :

int a;int *ptra=4;ptr=&a;

opérations avec contenus :

*ptr=*ptr+1; /* effet connu */

opérations avec pointeurs :

ptr = ptr+1; /* quel effets ??? */

Page 35: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Manipulationsopérations avec contenus :

*ptr=*ptr+1;

effet : calcule : contenu de ptr +1 : 4 +1 5, rangé dans contenu de ptr

opérations avec pointeurs :

ptr = ptr+1; /* quel effet ??? */

ptr désigne la flèche.

Page 36: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

ManipulationsÉtat des variables :

ptr

a

4

a est situé quelque part en mémoire

&a

*ptr

a: qqpart

ptr

Page 37: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Manipulationsa est situé quelque part en mémoire

nn+1n+2n+3n+4n+5n+6

4

ptr&a

Page 38: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

ManipulationsFaire ptr = ptr+1; change la flèche elle-même.

a+1:autre part

ptr

Page 39: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Manipulations

Arithmétique des pointeurs :

ajouter un entier à un pointeur : p pointeur et n entier.

p=p+n;

effet : p (et non son contenu) pointe n.t octets plus loin dans la mémoire (t : taille du type en octets).

soustraction de 2 pointeurs : p et q pointeurs sur un même type;

p-q;

effet : donne la taille de la mémoire située entre p et q.

Page 40: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Manipulations

Programme exemple : rappel : 1 variable float occupe 4 octets

#include <stdio.h>

void main(){

float x_1, x_2, x_3;float *p_fl;

x_3 = 1.3E+4;

p_fl=&x_1;p_fl = p_fl+2;printf("%f\n",*p_fl);

}

Page 41: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

nn+1n+2n+3n+4n+5n+6n+7n+8n+9

n+10n+11

p_fl

x_3 = 1.3E+4;

p_fl = &x_1;p_fl = p_fl+2;printf("%f\n",*p_fl);

1.3E+4

Place prévue pour stocker x_1

Place prévue pour stocker x_2

?

Page 42: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

nn+1n+2n+3n+4n+5n+6n+7n+8n+9

n+10n+11

p_fl

x_3 = 1.3E+4;

p_fl = &x_1;p_fl = p_fl+2;printf("%f\n",*p_fl);

1.3E+4

Place prévue pour stocker x_1

Place prévue pour stocker x_2

&x_1

Page 43: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

nn+1n+2n+3n+4n+5n+6n+7n+8n+9

n+10n+11

p_fl

x_3 = 1.3E+4;

p_fl = &x_1;p_fl = p_fl+2;printf("%f\n",*p_fl);

1.3E+4

Place prévue pour stocker x_1

Place prévue pour stocker x_2

Page 44: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

x_3 = 1.3E+4;

p_fl = &x_1;p_fl = p_fl+2;printf("%f\n",*p_fl);

1.3E+4

Page 45: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Manipulations

Programme exemple : rappel : 1 variable float occupe 4 octets

#include <stdio.h>

void main(){

float x_1, x_2, x_3;float *p_fl;float *q_fl;

p_fl=&x_1;q_fl=&x_3;printf("%d\n",q_fl-p_fl);

}

Page 46: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

nn+1n+2n+3n+4n+5n+6n+7n+8n+9

n+10n+11

p_fl

p_fl=&x_1;q_fl=&x_3;

printf("%d\n",q_fl-p_fl);

Place prévue pour stocker x_1

Place prévue pour stocker x_2

Place prévue pour stocker x_3

q_fl

?

?

Page 47: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

nn+1n+2n+3n+4n+5n+6n+7n+8n+9

n+10n+11

p_fl

p_fl=&x_1;q_fl=&x_3;

printf("%d\n",q_fl-p_fl);

Place prévue pour stocker x_1

Place prévue pour stocker x_2

Place prévue pour stocker x_3

q_fl

&x_1

&x_3

Page 48: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Manipulations

p_fl=&x_1;q_fl=&x_3;printf("%d\n",q_fl-p_fl);

2

Page 49: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs et tableauxRelation entre tableaux et pointeurs

un tableau est un pointeur !

Donne accès au premier élément du tableau… pointe sur le premier élément du tableau !

char tab[4]; se représente ainsi :

tab

Stockage d'un char tab[0]

Stockage d'un char tab[1]

Stockage d'un char tab[2]

Stockage d'un char tab[3]

Page 50: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs et tableaux

tab

Stockage d'un char tab[0]

Stockage d'un char tab[1]

Stockage d'un char tab[2]

Stockage d'un char tab[3]

&tab[0]

En fait tab = &tab[0]

par contre tab est constant : non modifiable

&tab[1]

&tab[2]

&tab[3]

On a : tab+i = &tab[i]

Page 51: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamique

Un tableau est alloué de manière statique : nombre d'éléments constant.

Alloué lors de la compilation (avant exécution)

problème pour déterminer la taille optimale, donnée à l'exécution

surestimation et perte de place

de plus, le tableau est un pointeur constant.

Il faudrait un système permettant d'allouer un nombre d'éléments connu seulement à l'exécution : c'est l'allocation dynamique.

Page 52: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamique

Faire le lien entre le pointeur non initialisé (le panneau vide) et une zone de mémoire de la taille que l'on veut.

On peut obtenir cette zone de mémoire par l'emploi de malloc, qui est une fonction prévue à cet effet.

Il suffit de donner à malloc le nombre d'octets désirés (attention, utilisation probable de sizeof), et malloc renvoie un pointeur de type void* sur la zone de mémoire allouée.

Si malloc n'a pas pu trouver une telle zone mémoire, il renvoie NULL.

Appel par : malloc(nombre_d_octets_voulus);

Page 53: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamique

Symbolisation de l'effet de malloc:

si on utilise par exemple malloc(n), on a :

Zone de n octets

malloc() renvoie le pointeur

Pour accéder à cette zone, il faut impérativement l'affecter à un pointeur existant. On trouvera donc toujours malloc à droite d'un opérateur d'affectation.

Il ne faut pas oublier de transtyper le résultat de malloc() qui est de type void* en le type du pointeur auquel on affecte le résultat.

Page 54: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamique

Exemples d'utilisation :

allocation dynamique pour un pointeur vers des entiers, (analogue à un tableau d'entiers). On demandera à l'utilisateur le nombre d'éléments qu'il souhaite, puis on fait l'allocation dynamique correspondante :

tableau de la taille requise, pas de perte de mémoire !#include <stdio.h>void main(){

int *pt_int;int nbElem;

printf("combien d'elements dans le tableau ?:");scanf("%d",&nbElem);

}

Page 55: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamique

pt_int = (int *)malloc(nbElem*sizeof(int));

détail de cette ligne : analyse de l'expression à droite de l'opérateur d'affectation :(int *) : transtypage : car malloc() donne un pointeur void *, et pt_int est de type int *malloc : appel à la fonctionnbElem*sizeof(int) : n'oublions pas que malloc reçoit un nombre d'octets a allouer ! Ici, on veut allouer nbElem élements, qui sont chacun de type int ! Or un int occupe plus d'un octet. Il occupe sizeof(int) octets !Donc le nombre total d'octets à demander est : nombre d'éléments * taille de chaque élément en octets.

Page 56: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamique

pt_int = (int *)malloc(nbElem*sizeof(int));

avec la symbolisation déjà vue pour les pointeurs :

pt_int

Zone de nbElem*sizeof(int)

octets

malloc() renvoie ce pointeur

Rôle de l'affectation

Page 57: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Allocation dynamiqueVérifier le fonctionnement : si malloc() à donné NULL, l'allocation a échoué. Toujours tester la valeur du pointeur affecté après l'emploi de malloc().

if (pt_int == NULL){

printf("allocation n'a pas fonctionne\");}else{

/* suite du programme */}

on peut maintenant utiliser pt_int comme un tableau d'entiers, avec la notation [] !

Page 58: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Libération de l'espace alloué

Lorsque la mémoire allouée dynamiquement n'est plus utile (le plus souvent, à la fin d'un programme, il est nécessaire de la libérer : la rendre disponible pour le système d'exploitation.

Fonction free qui réalise le contraire de malloc().

free(pointeur_vers_la_zone_allouée);

on ne peut libérer que des zones allouées dynamiquement : pas de free avec un tableau statique, même si le compilateur l'accepte.

pt_int

Zone allouée par malloc

Page 59: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Libération de l'espace alloué

Si on écrit : free(pt_int);

effet :

pt_int pointe toujours au même endroit de la mémoire, mais on ne peut plus l'utiliser.

À chaque malloc() doit correspondre un free() dans un programme !

Sinon, l'ordinateur le fait à votre place : ne lui faites pas confiance !

pt_int

Page 60: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs de pointeurs

Un pointeur est une variable (presque) comme une autre : elle possède un type, une valeur (qui est une adresse), un nom, et aussi une adresse !

Ne pas confondre valeur d'un pointeur et adresse d'un pointeur !

À ce titre, on peut tout à fait employer l'opérateur de prise d'adresse & à un pointeur.

Mais quel sera alors le type de cette expression ?

Soit ptr_fl un pointeur sur une valeur float par exemple, déjà initialisé (peu importe comment).

&ptr_fl est une expression valide, mais quel est son type ?

Page 61: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

nn+1n+2n+3

mm+1m+2m+3

ptr_fl

Une valeur de type float

Place prévue pour stocker ptr_fl

&ptr_fl

Page 62: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs de pointeurs

On sait que ptr_fl est défini par son contenu, quand on écrit sa déclaration :

float *ptr_fl; /* lire :le contenu de ptr_fl est un float */

le contenu de &ptr_fl, c'est ptr_fl, dont le contenu est un float.

Donc : le contenu du contenu de &ptr_fl est un float : c'est ainsi que l'on trouve le type de l'expression &ptr_fl : c'est un pointeur de pointeur de float !

&ptr_fl est un panneau indiquant où se trouve un autre panneau.

Les pointeurs de pointeurs sont-ils utiles ? Oui (malheureusement pour vous...) pour représenter les tableaux à plusieurs dimensions ainsi que des structures de données complexes.

Page 63: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs de pointeurs

Exemple de déclaration et d'utilisation.

void main(){

char **dblPoint;char *simpPoint;char v;

simpPoint=&v;dbPoint = &simpPoint;

}

lecture habituelle : •le contenu du contenu de dblPoint est de type char : c'est un pointeur de pointeur•le contenu de simpPoint est de type char : c'est un pointeur•v est de type char

Page 64: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Pointeurs de pointeurs

Il est possible d'étendre ce raisonnement à plusieurs niveaux (plus que 2). Avec un peu d'habitude, il est possible d'écrire (et d'utiliser surtout !):

char ****maillage3D;

ce qui au fond, n'a rien de bien impressionnant.

Page 65: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Tableau de pointeurs

Puisqu'un pointeur est une variable comme une autre, on peut aussi les ranger dans un tableau: restriction, il faut que les pointeurs soient tous des pointeurs vers le même type.

Pour la déclaration :

type *tab[NB_ELEM] signifie : le contenu de chaque case du tableau est une valeur ayant le type donné, ou encore ; chaque case du tableau est un pointeur.

On peut s'en servir, par exemple, pour gérer un petit dictionnaire, c'est l'exemple que nous allons développer dans la suite du cours.

Page 66: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Tableau de pointeurs

Nous allons considérer un 'petit' dictionnaire de 200 mots maximum. Puisque l'on connaît la taille maximum, on va donc le stocker sous la forme d'un tableau contenant des mots, où plutôt des chaînes de caractères. Par contre, tous les mots n'ayant pas la même taille, on devra utiliser juste la mémoire nécessaire à les stocker, grâce à une allocation dynamique pour chacun des mots que l'on voudra stocker.

Page 67: Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',

Double allocation dynamique