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',

Slides:



Advertisements
Présentations similaires
Premier programme en C :
Advertisements

La boucle for : init7.c et init71.c
Introduction au Langage C,C++
Introduction Langage très répandu Noyau Linux VLC … Des avantages indéniables mais aussi des contraintes ! Ceci nest quun rapide tour.
Rappels C.
Algorithmique Résume.
GEF 243B Programmation informatique appliquée
C.
Paramètres et pointeurs
Structures et unions types énumérés Qu'est-ce qu'une structure
Suite à de nombreuses remarques concernant le projet de structures de données 'Gestion d'un Aéroport' , voici un polycopié de cours concernant la gestion.
Tableaux Certains problèmes nécessitent beaucoup de variables du même type. Exemple : relevé de températures matin et soir dans 10 villes pour 10 jours.
Chap. 1 Structures séquentielles : listes linéaires
Fonctions Dans un programme : certaines opérations (ou séquences d'opérations) peuvent se répéter plusieurs fois : affichage de tableau, saisie, ou même.
FLSI602 Génie Informatique et Réseaux
FLSI602 Génie Informatique et Réseaux
8. Les tableaux P. Costamagna – ISEN N1.
Les bases de l’Algorithmique
Regrouper des éléments de même type et pouvoir y accéder à laide dun identificateur et dun indice. Objectif des tableaux.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Structures de données linéaires
Récursivité.
RESUMES Module II1 SOMMAIRE CYCLE 1 : Saisir – Afficher – Données
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
La fonction alloue un bloc de taille size. Il faut indiquer la taille du bloc que lon veut allouer. Le premier exemple: #include void main()
TRAITEMENT DE STRUCTURES
IFT-2000: Structures de Données Listes chaînées Dominic Genest, 2009.
Les Classes les structures en C (struct) regroupent des variables : structuration de l'analyse mais problèmes de cohérence problèmes de sécurité d'accès.
Quest-ce quune classe dallocation? Une classe dallocation détermine la portée et la durée de vie dun objet ou dune fonction.
Les pointeurs Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert?
Les fichiers binaires en C++
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
8PRO100 Éléments de programmation Les types composés.
Méthode et Outils pour la Programmation
C++ : variables Déclaration de variables
Tableaux Introduction aux tableaux à une dimension. Déclaration, stockage, initialisation et accès en lecture ou en écriture aux composantes d’un tableau.
Procédures et fonctions
Plan cours La notion de pointeur et d’adresse mémoire.
Types de données fondamentaux
L’essentiel du langage C
Le langage C Structures de données
2.1 - Historique Chapitre 2 : Introduction au langage C++
Les pointeurs L'opérateur &.
Le langage C Rappel Pointeurs & Allocation de mémoire.
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
Notions de pointeurs en C
et quelques rappels sur certains éléments du langage C
Les adresses des fonctions
Un survol du language C.
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
La fonction alloue un bloc de taille size. Il faut indiquer la taille du bloc que l’on veut allouer. Le premier exemple: #include void main()
Tutorat en bio-informatique
ISBN Chapitre 10 L'implémentation des sous- programmes.
Cours LCS N°4 Présenté par Mr: LALLALI
Classe 1 CSI2572 Autres modificateurs de déclaration de variables: & volatile & register & static & auto & extern & const volatile Indique au compilateur.
Les variables fichiers. Le type fichier On manipule les fichiers par l’intermédiaire de structures FILE décrites dans stdio.h FILE *monFichier; –Nom physique.
1. Spoon Christophe Delagarde, septembre 1998 I.U.T., Université de la Méditerrainée 2.
Conception de Programmes - IUT de Paris - 1ère année Quelques éléments du langage C++ Les références La surcharge de fonctions Les fonctions «
8PRO107 Éléments de programmation Les adresses et les pointeurs.
3ième Classe (Mardi, 23 Septembre) CSI2572. O jourd'8: E Allocation de mémoire E Déallocation de mémoire E Tableaux (n dimensions) E Arithmetique des.
Philippe Gandy – 10 novembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Informatique 2A Langage C 5ème séance. Déroulement de la séance 5 1 ère partie Étude des chaînes de caractères 2 ème partie Les structures 3.
Informatique 1A Langage C 6 ème séance 1. Objectifs de la séance 6  Allocation dynamique de mémoire  Application à la création de tableaux 2.
Informatique 2A Langage C 3 ème séance.
Transcription de la présentation:

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 !

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 ?

Attention à la distinction adresse/contenu 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

Les adresses Schématisation de la mémoire : contenus adresse n n+1 n+2 Cellules consécutives

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.

Les adresses 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); } 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)

Invisible pour le programmeur ou l'utilisateur Les adresses Lorsque l'on utilise val1, la machine va consulter l'adresse 1000 1000 1001 1002 1003 1004 1005 1006 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

Le nom de la variable "masque" son adresse Les adresses void main() { int val1,val2; val1 = 3; val2 = -2*val1+4; if (val2 < val1) printf("%d < %d\n",val2,val1); } Le compilateur utilise sa table de correspondance : val1  adresse 1000 Le nom de la variable "masque" son adresse

Les adresses Effet de l'instruction val1 = 3; en mémoire 1000 1001 1002 1003 1004 1005 1006 3 Valeur stockée dans val2

Les adresses void main() { int val1,val2; val1 = 3; val2 = -2*val1+4; if (val2 < val1) printf("%d < %d\n",val2,val1); } Le compilateur utilise sa table de correspondance pour val1 et val2

Les adresses Effet de l'instruction val2 = -2*val1+4; en mémoire 1000 1001 1002 1003 1004 1005 1006 3 -2

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

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 Représente la variable val1 &val1 val1 Représente l'adresse de val1

Les adresses On peut aussi voir cette flèche comme un panneau indicateur que l'on peut consulter. Val1: adresse 1000 Représente &val1

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

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

*ptr se lit : contenu de ptr. 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.

Les pointeurs : illustration Si ptr vaut 1002 : *ptr est ce qui est contenu à l'adresse 1002 : 0 ptr 1002 1000 1001 1002 1003 1004 1005 1006 3 15 -845 6311

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.

toujours lire * comme 'contenu' ! 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' !

É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

É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 43 ptr

É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

É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 43 Égalité entres les flèches

État du pointeur après déclaration ptr var1 43 Ou encore : Var1: qqpart ptr

État du pointeur après déclaration Maintenant, ptr pointe sur var1, le panneau indique une destination que fait la ligne suivante : *ptr=5; ? ptr Avant cette ligne : var1 43 À vous de jouer ptr Après cette ligne : var1

État du pointeur après déclaration Reprise de l'exemple avec le schéma de la mémoire : n n+1 n+2 n+3 n+4 n+5 n+6 short int var1; short int *ptr; var1 = 43; ptr=&var1; *ptr = 5; ? Effet : 2 octets utilisés pour stocker un short int.

État du pointeur après déclaration Reprise de l'exemple avec le schéma de la mémoire : n n+1 n+2 n+3 n+4 n+5 n+6 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.

État du pointeur après déclaration Reprise de l'exemple avec le schéma de la mémoire : n n+1 n+2 n+3 n+4 n+5 n+6 short int var1; short int *ptr; var1 = 43; ptr=&var1; *ptr = 5; 43 ? Effet : stocker 43 dans var1.

État du pointeur après déclaration Reprise de l'exemple avec le schéma de la mémoire : &var1 n n+1 n+2 n+3 n+4 n+5 n+6 short int var1; short int *ptr; var1 = 43; ptr=&var1; *ptr = 5; 43 Effet : fait pointer ptr sur var1.

État du pointeur après déclaration Reprise de l'exemple avec le schéma de la mémoire : &var1 n n+1 n+2 n+3 n+4 n+5 n+6 short int var1; short int *ptr; var1 = 43; ptr=&var1; *ptr = 5; 5 Effet : stocke 5 dans le contenu de ptr.

Manipulations Que 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; }

Manipulations Que 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; }

Soient les instructions suivantes : Manipulations Soient les instructions suivantes : int a; int *ptr a=4; ptr=&a; opérations avec contenus : *ptr=*ptr+1; /* effet connu */ opérations avec pointeurs : ptr = ptr+1; /* quel effets ??? */

Manipulations opé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.

a est situé quelque part en mémoire Manipulations État des variables : ptr &a a *ptr 4 a: qqpart ptr a est situé quelque part en mémoire

Manipulations n n+1 n+2 n+3 n+4 n+5 n+6 4 a est situé quelque part en mémoire ptr &a n n+1 n+2 n+3 n+4 n+5 n+6 4

Manipulations Faire ptr = ptr+1; change la flèche elle-même. ptr a+1:autre part ptr

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.

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); }

Place prévue pour stocker x_1 n n+1 n+2 n+3 n+4 n+5 n+6 n+7 n+8 n+9 n+10 n+11 Place prévue pour stocker x_1 p_fl ? Place prévue pour stocker x_2 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 p_fl &x_1 n n+1 n+2 n+3 n+4 n+5 n+6 n+7 n+8 n+9 n+10 n+11 Place prévue pour stocker x_1 Place prévue pour stocker x_2 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 x_3 = 1.3E+4; p_fl = &x_1; p_fl = p_fl+2; printf("%f\n",*p_fl); n n+1 n+2 n+3 n+4 n+5 n+6 n+7 n+8 n+9 n+10 n+11 Place prévue pour stocker x_1 Place prévue pour stocker x_2 p_fl 1.3E+4

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

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); }

Place prévue pour stocker x_1 ? n n+1 n+2 n+3 n+4 n+5 n+6 n+7 n+8 n+9 n+10 n+11 p_fl Place prévue pour stocker x_1 ? q_fl ? Place prévue pour stocker x_2 p_fl=&x_1; q_fl=&x_3; printf("%d\n",q_fl-p_fl); Place prévue pour stocker x_3

Place prévue pour stocker x_1 p_fl &x_1 n n+1 n+2 n+3 n+4 n+5 n+6 n+7 n+8 n+9 n+10 n+11 Place prévue pour stocker x_1 Place prévue pour stocker x_2 q_fl &x_3 p_fl=&x_1; q_fl=&x_3; printf("%d\n",q_fl-p_fl); Place prévue pour stocker x_3

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

Pointeurs et tableaux Relation 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]

Pointeurs et tableaux En fait tab = &tab[0] par contre tab est constant : non modifiable tab &tab[0] Stockage d'un char tab[0] &tab[1] Stockage d'un char tab[1] &tab[2] Stockage d'un char tab[2] &tab[3] Stockage d'un char tab[3] On a : tab+i = &tab[i]

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.

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);

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.

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); }

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 fonction nbElem*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.

Zone de nbElem*sizeof(int) octets Allocation dynamique pt_int = (int *)malloc(nbElem*sizeof(int)); avec la symbolisation déjà vue pour les pointeurs : pt_int malloc() renvoie ce pointeur Zone de nbElem*sizeof(int) octets Rôle de l'affectation

Allocation dynamique Vé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 [] !

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

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

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 ?

Une valeur de type float ptr_fl n n+1 n+2 n+3 m m+1 m+2 m+3 Une valeur de type float &ptr_fl Place prévue pour stocker ptr_fl

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.

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

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.

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.

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.

Double allocation dynamique