Chapitre 3 Les pointeurs
Toute variable manipul e dans un programme est stock e quelque part en m moire centrale. Cette
m moire est constitu e d'octets 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 de l'octet o elle est stock e
(ou, s'il s'agit d'une variable qui recouvre plusieurs octets contigus, l'adresse du premier de ces octets).
Pour des raisons videntes de lisibilit , on d signe souvent les variables par des identificateurs, et non
par leur adresse. C'est le compilateur qui fait alors 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.
3.1 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.
Dans l'exemple,
int i, j;
i = 3;
j = i;
Si le compilateur a plac la variable i l'adresse 4831836000 en m moire, et la variable j l'adresse
4831836004, on a
objet
i
j
adresse
4831836000
4831836004
valeur
3
3
Deux variables diff rentes ont des adresses diff rentes. L'affectation i = j; n'op re que sur les
valeurs des variables. Les variables i et j tant de type int, elles sont stock es sur 4 octets. Ainsi la
valeur de i est stock e sur les octets d'adresse 4831836000 4831836003.
L'adresse d'un objet tant un num ro d'octet en m moire, il s'agit d'un entier quelque soit le type de
l'objet consid r . Le format interne de cet entier (16 bits, 32 bits ou 64 bits) d pend des architectures.
Sur un DEC alpha, par exemple, une adresse a toujours le format d'un entier long (64 bits).
L'op rateur & permet d'acc der l'adresse d'une variable. Toutefois &i n'est pas une Lvalue mais une
constante : on ne peut pas faire figurer &i gauche d'un op rateur d'affectation. Pour pouvoir
manipuler des adresses, on doit donc recourir un nouveau type d'objets, les pointeurs.
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html1/133.2 Notion de pointeur
Un pointeur est un objet (Lvalue) dont la valeur est gale l'adresse d'un autre objet. On d clare un
pointeur par l'instruction :
type *nomdupointeur;
o type est le type de l'objet point . Cette d claration d clare un identificateur, nomdupointeur,
associ un objet dont la valeur est l'adresse d'un autre objet de type type. L'identificateur nomdu
pointeur est donc en quelque sorte un identificateur d'adresse. Comme pour n'importe quelle Lvalue,
sa valeur est modifiable.
M me si la valeur d'un pointeur est toujours un entier ( ventuellement un entier long), le type d'un
pointeur d pend du type de l'objet vers lequel il pointe. Cette distinction est indispensable
l'interpr tation de la valeur d'un pointeur. En effet, pour un pointeur sur un objet de type char, la
valeur donne l'adresse de l'octet o cet objet est stock . Par contre, pour un pointeur sur un objet de
type int, la valeur donne l'adresse du premier des 4 octets o l'objet est stock . Dans l'exemple
suivant, on d finit un pointeur p qui pointe vers un entier i :
int i = 3;
int *p;
p = &i;
On se trouve dans la configuration
objet
i
p
adresse
4831836000
4831836004 4831836000
valeur
3
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 = &i;
printf("p = %d \n",p);
}
imprime *p = 3.
Dans ce programme, les objets i et *p sont identiques : ils ont m mes adresse et valeur. Nous sommes
dans la configuration :
objet
i
adresse
4831836000
4831836004 4831836000
valeur
3
p
*p 4831836000
3
Cela signifie en particulier que toute modification de p modifie i. Ainsi, si l'on ajoute l'instruction p
= 0; la fin du programme pr c dent, la valeur de i devient nulle.
On peut donc dans un programme manipuler la fois les objets p et *p. Ces deux manipulations sont
tr s diff rentes. Comparons par exemple les deux programmes suivants :
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html2/13
main()
{
int i = 3, j = 6;
int p1, p2;
p1 = &i;
p2 = &j;
p1 = p2;
}
et
main()
{
int i = 3, j = 6;
int p1, p2;
p1 = &i;
p2 = &j;
p1 = p2;
}
Avant la derni re affectation de chacun de ces programmes, on est dans une configuration du type :
objet
i
adresse
4831836000
4831836004
valeur
3
6
j
p1 4831835984 4831836000
p2 4831835992 4831836004
Apr s l'affectation p1 = p2; du premier programme, on a
objet
i
adresse
Publicité
4831836000
4831836004
valeur
6
6
j
p1 4831835984 4831836000
p2 4831835992 4831836004
Par contre, l'affectation p1 = p2 du second programme, conduit la situation :
objet
i
adresse
4831836000
4831836004
valeur
3
6
j
p1 4831835984 4831836004
p2 4831835992 4831836004
3.3 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 de
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 pointant tous deux vers des objets de m me type. Le r sultat est
un entier.
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html3/13Notons que la somme de deux pointeurs n'est pas autoris e.
Si i est un entier et p est un pointeur sur un objet de type type, l'expression p + i d signe un pointeur
sur un objet de type type dont la valeur est gale la valeur de p incr ment e de i * sizeof(type). Il
en va de m me pour la soustraction d'un entier un pointeur, et pour les op rateurs d'incr mentation
et de d cr mentation ++ et . Par exemple, le programme
main()
{
int i = 3;
int p1, p2;
p1 = &i;
p2 = p1 + 1;
printf("p1 = %ld \t p2 = %ld\n",p1,p2);
}
affiche p1 = 4831835984 p2 = 4831835988.
Par contre, le m me programme avec des pointeurs sur des objets de type double :
main()
{
double i = 3;
double p1, p2;
p1 = &i;
p2 = p1 + 1;
printf("p1 = %ld \t p2 = %ld\n",p1,p2);
}
affiche p1 = 4831835984 p2 = 4831835992.
Les op rateurs de comparaison sont galement applicables aux pointeurs, condition de comparer des
pointeurs qui pointent vers des objets de m me type.
L'utilisation des op rations arithm tiques sur les pointeurs est particuli rement utile pour parcourir des
tableaux. Ainsi, le programme suivant imprime les l ments du tableau tab dans l'ordre croissant puis
d croissant des indices.
#define N 5
int tab[5] = {1, 2, 6, 0, 7};
main()
{
int *p;
printf("\n ordre croissant:\n");
for (p = &tab[0]; p <= &tab ; p++)
printf(" %d \n",*p);
printf("\n ordre decroissant:\n");
for (p = &tab ; p >= &tab[0]; p)
printf(" %d \n",*p);
}
Si p et q sont deux pointeurs sur des objets de type type, l'expression p q d signe un entier dont la
valeur est gale (p q)/sizeof(type) .
3.4 Allocation dynamique
Avant de manipuler un pointeur, et notamment de lui appliquer l'op rateur d'indirection *, il faut
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html4/13l'initialiser. 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. Le test p == NULL permet de savoir si le
pointeur p pointe vers un objet.
On peut initialiser un pointeur p par une affectation sur p. Par exemple, on peut affecter p l'adresse
d'une autre variable. Il est galement possible d'affecter directement une valeur *p. Mais pour cela, 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
malloc(nombreoctets)
Cette fonction retourne un pointeur de type char * pointant vers un objet de taille nombreoctets octets.
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. L'argument nombreoctets est souvent donn l'aide de
la fonction sizeof() qui renvoie le nombre d'octets utilis s pour stocker un objet.
Ainsi, pour initialiser un pointeur vers un entier, on crit :
#include <stdlib.h>
int *p;
p = (int*)malloc(sizeof(int));
On aurait pu crire galement
p = (int*)malloc(4);
puisqu'un objet de type int est stock sur 4 octets. Mais on pr f rera la premi re criture qui a
l'avantage d' tre portable.
Le programme suivant
#include <stdio.h>
#include <stdlib.h>
main()
{
int i = 3;
int *p;
printf("valeur de p avant initialisation = %ld\n",p);
p = (int*)malloc(sizeof(int));
printf("valeur de p apres initialisation = %ld\n",p);
*p = i;
printf("valeur de p = %d\n",p);
}
d finit un pointeur p sur un objet p de type int, et affecte p la valeur de la variable i. Il imprime
l' cran :
valeur de p avant initialisation = 0
valeur de p apres initialisation = 5368711424
valeur de *p = 3
Avant l'allocation dynamique, on se trouve dans la configuration
valeur
3
0
adresse
4831836000
4831836004
objet
i
p
Publicité
A ce stade, p n'a aucun sens. En particulier, toute manipulation de la variable p g n rerait une
violation m moire, d tectable l'ex cution par le message d'erreur Segmentation fault.
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html5/13L'allocation dynamique a pour r sultat d'attribuer une valeur p et de r server cette adresse un
espace m moire compos de 4 octets pour stocker la valeur de *p. On a alors
objet
i
adresse
4831836000
4831836004 5368711424
valeur
3
p
*p 5368711424
? (int)
p est maintenant d finie mais sa valeur n'est pas initialis e. Cela signifie que p peut valoir n'importe
quel entier (celui qui se trouvait pr c demment cette adresse). L'affectation *p = i; a enfin pour
r sultat d'affecter *p la valeur de i. A la fin du programme, on a donc
objet
i
adresse
4831836000
4831836004 5368711424
valeur
3
p
*p 5368711424
3
Il est important de comparer le programme pr c dent avec
main()
{
int i = 3;
int *p;
p = &i;
}
qui correspond la situation
objet
i
adresse
4831836000
4831836004 4831836000
valeur
3
p
*p 4831836000
3
Dans ce dernier cas, les variables i et *p sont identiques (elles ont la m me adresse) ce qui implique
que toute modification de l'une modifie l'autre. Ceci n' tait pas vrai dans l'exemple pr c dent o *p et
i avaient la m me valeur mais des adresses diff rentes.
On remarquera que le dernier programme ne n cessite pas d'allocation dynamique puisque l'espace
m moire l'adresse &i est d j r serv pour un entier.
La fonction malloc permet galement d'allouer un espace pour plusieurs objets contigus en m moire.
On peut crire par exemple
#include <stdio.h>
#include <stdlib.h>
main()
{
int i = 3;
int j = 6;
int *p;
p = (int)malloc(2 sizeof(int));
*p = i;
*(p + 1) = j;
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html6/13
printf("p = %ld \t p = %d \t p+1 = %ld \t (p+1) = %d \n",p,p,p+1,(p+1));
}
On a ainsi r serv , l'adresse donn e par la valeur de p, 8 octets en m moire, qui permettent de
stocker 2 objets de type int. Le programme affiche
p = 5368711424 p = 3 p+1 = 5368711428 (p+1) = 6 .
La fonction calloc de la librairie stdlib.h a le m me r le que la fonction malloc mais elle initialise en
plus l'objet point *p z ro. Sa syntaxe est
calloc(nbobjets,tailleobjets)
Ainsi, si p est de type int*, l'instruction
p = (int*)calloc(N,sizeof(int));
est strictement quivalente
p = (int)malloc(N sizeof(int));
for (i = 0; i < N; i++)
*(p + i) = 0;
L'emploi de calloc est simplement plus rapide.
Enfin, lorsque l'on n'a plus besoin de l'espace m moire allou dynamiquement (c'est dire quand on
n'utilise plus le pointeur p), il faut lib rer cette place en m moire. Ceci se fait l'aide de l'instruction
free qui a pour syntaxe
A toute instruction de type malloc ou calloc doit tre associ e une instruction de type free.
free(nomdupointeur);
3.5 Pointeurs et tableaux
L'usage des pointeurs en C est, en grande partie, orient vers la manipulation des tableaux.
3.5.1 Pointeurs et tableaux 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 tab
pour parcourir les l ments du tableau.
#define N 5
int tab[5] = {1, 2, 6, 0, 7};
main()
{
int i;
int *p;
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html7/13 p = tab;
for (i = 0; i < N; i++)
{
printf(" %d \n",*p);
p++;
}
}
On acc de l' l ment d'indice i du tableau tab gr ce l'op rateur d'indexation [], par l'expression
tab . Cet op rateur d'indexation peut en fait s'appliquer tout objet p de type pointeur. Il est li
l'op rateur d'indirection * par la formule
p = *(p + i)
Pointeurs et tableaux se manipulent donc exactement de m me mani re. Par exemple, le programme
pr c dent peut aussi s' crire
#define N 5
int tab[5] = {1, 2, 6, 0, 7};
main()
{
int i;
int *p;
p = tab;
for (i = 0; i < N; i++)
printf(" %d \n", p );
}
Toutefois, la manipulation de tableaux, et non de pointeurs, poss de certains inconv nients d s au fait
qu'un tableau est un pointeur constant. Ainsi
on ne peut pas cr er de tableaux dont la taille est une variable du programme,
on ne peut pas cr er de tableaux bidimensionnels dont les lignes n'ont pas toutes le m me
Publicité
nombre d' l ments.
Ces op rations deviennent possibles d s que l'on manipule des pointeurs allou s dynamiquement.
Ainsi, pour cr er un tableau d'entiers n l ments o n est une variable du programme, on crit
#include <stdlib.h>
main()
{
int n;
int *tab;
...
tab = (int)malloc(n sizeof(int));
...
free(tab);
}
Si on veut en plus que tous les l ments du tableau tab soient initialis s z ro, on remplace
l'allocation dynamique avec malloc par
tab = (int*)calloc(n, sizeof(int));
Les l ments de tab sont manipul s avec l'op rateur d'indexation [], exactement comme pour les
tableaux.
Les deux diff rences principales entre un tableau et un pointeur sont
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html8/13
un pointeur doit toujours tre initialis , soit par une allocation dynamique, soit par affectation
d'une expression adresse, par exemple p = &i ~
un tableau n'est pas une Lvalue ~ il ne peut donc pas figurer gauche d'un op rateur
d'affectation. En particulier, un tableau ne supporte pas l'arithm tique (on ne peut pas crire
tab++;).
3.5.2 Pointeurs et tableaux plusieurs dimensions
Un tableau deux dimensions est, par d finition, un tableau de tableaux. Il s'agit donc en fait d'un
pointeur vers un pointeur. Consid rons le tableau deux dimensions d fini par :
int tab ;
tab est un pointeur, qui pointe vers un objet lui m me de type pointeur d'entier. tab a une valeur
constante gale l'adresse du premier l ment du tableau, &tab[0][0]. De m me tab , pour i
entre 0 et M1, est un pointeur constant vers un objet de type entier, qui est le premier l ment de la
ligne d'indice i. tab a donc une valeur constante qui est gale &tab [0].
Exactement comme pour les tableaux une dimension, les pointeurs de pointeurs ont de nombreux
avantages sur les tableaux multi dimensionn s.
On d clare un pointeur qui pointe sur un objet de type type * (deux dimensions) de la m me mani re
qu'un pointeur, c'est dire
type **nomdupointeur;
De m me un pointeur qui pointe sur un objet de type type ** ( quivalent un tableau 3 dimensions)
se d clare par
Par exemple, pour cr er avec un pointeur de pointeur une matrice k lignes et n colonnes
coefficients entiers, on crit :
type *nomdupointeur;
main()
{
int k, n;
int **tab;
tab = (int*)malloc(k sizeof(int*));
for (i = 0; i < k; i++)
tab = (int)malloc(n sizeof(int));
....
for (i = 0; i < k; i++)
free(tab );
free(tab);
}
La premi re allocation dynamique r serve pour l'objet point par tab l'espace m moire correspondant
k pointeurs sur des entiers. Ces k pointeurs correspondent aux lignes de la matrice. Les allocations
dynamiques suivantes r servent pour chaque pointeur tab l'espace m moire n cessaire pour
stocker n entiers.
Si on d sire en plus que tous les l ments du tableau soient initialis s z ro, il suffit de remplacer
l'allocation dynamique dans la boucle for par
tab = (int*)calloc(n, sizeof(int));
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html9/13Contrairement aux tableaux deux dimensions, on peut choisir des tailles diff rentes pour chacune
des lignes tab . Par exemple, si l'on veut que tab contienne exactement i+1 l ments, on crit
for (i = 0; i < k; i++)
tab = (int)malloc((i + 1) sizeof(int));
3.5.3 Pointeurs et cha nes de caract res
On a vu pr c demment qu'une cha ne de caract res tait un tableau une dimension d'objets de type
char, se terminant par le caract re nul '\0'. On peut donc manipuler toute cha ne de caract res l'aide
d'un pointeur sur un objet de type char. On peut faire subir une cha ne d finie par
char *chaine;
des affectations comme
chaine = "ceci est une chaine";
et toute op ration valide sur les pointeurs, comme l'instruction chaine++;. Ainsi, le programme
suivant imprime le nombre de caract res d'une cha ne (sans compter le caract re nul).
#include <stdio.h>
main()
{
int i;
char *chaine;
chaine = "chaine de caracteres";
for (i = 0; *chaine != '\0'; i++)
chaine++;
printf("nombre de caracteres = %d\n",i);
}
La fonction donnant la longueur d'une cha ne de caract res, d finie dans la librairie standard string.h,
proc de de mani re identique. Il s'agit de la fonction strlen dont la syntaxe est
strlen(chaine);
o chaine est un pointeur sur un objet de type char. Cette fonction renvoie un entier dont la valeur est
gale la longueur de la cha ne pass e en argument (moins le caract re '\0'). L'utilisation de
pointeurs de caract re et non de tableaux permet par exemple de cr er une cha ne correspondant la
concat nation de deux cha nes de caract res :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
int i;
char chaine1, chaine2, res, p;
chaine1 = "chaine ";
chaine2 = "de caracteres";
res = (char)malloc((strlen(chaine1) + strlen(chaine2)) sizeof(char));
p = res;
for (i = 0; i < strlen(chaine1); i++)
*p++ = chaine1 ;
for (i = 0; i < strlen(chaine2); i++)
*p++ = chaine2 ;
printf("%s\n",res);
}
On remarquera l'utilisation d'un pointeur interm diaire p qui est indispensable d s que l'on fait des
op rations de type incr mentation. En effet, si on avait incr ment directement la valeur de res, on
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html10/13
aurait videmment ``perdu'' la r f rence sur le premier caract re de la cha ne. Par exemple,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
int i;
char chaine1, chaine2, *res;
chaine1 = "chaine ";
chaine2 = "de caracteres";
res = (char)malloc((strlen(chaine1) + strlen(chaine2)) sizeof(char));
for (i = 0; i < strlen(chaine1); i++)
Publicité
*res++ = chaine1 ;
for (i = 0; i < strlen(chaine2); i++)
*res++ = chaine2 ;
printf("\nnombre de caracteres de res = %d\n",strlen(res));
}
imprime la valeur 0, puisque res a t modifi au cours du programme et pointe maintenant sur le
caract re nul.
3.6 Pointeurs et structures
3.6.1 Pointeur sur une structure
Contrairement aux tableaux, les objets de type structure en C sont des Lvalues. Ils poss dent une
adresse, correspondant l'adresse du premier l ment du premier membre de la structure. On peut
donc manipuler des pointeurs sur des structures. Ainsi, le programme suivant cr e, l'aide d'un
pointeur, un tableau d'objets de type structure.
#include <stdlib.h>
#include <stdio.h>
struct eleve
{
char nom[20];
int date;
};
typedef struct eleve *classe;
main()
{
int n, i;
classe tab;
printf("nombre d'eleves de la classe = ");
scanf("%d",&n);
tab = (classe)malloc(n * sizeof(struct eleve));
for (i =0 ; i < n; i++)
{
printf("\n saisie de l'eleve numero %d\n",i);
printf("nom de l'eleve = ");
scanf("%s",&tab .nom);
printf("\n date de naissance JJMMAA = ");
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html11/13
scanf("%d",&tab .date);
}
printf("\n Entrez un numero ");
scanf("%d",&i);
printf("\n Eleve numero %d:",i);
printf("\n nom = %s",tab .nom);
printf("\n date de naissance = %d\n",tab .date);
free(tab);
}
Si p est un pointeur sur une structure, on peut acc der un membre de la structure point par
l'expression
(*p).membre
L'usage de parenth ses est ici indispensable car l'op rateur d'indirection * une priorit plus lev e
que l'op rateur de membre de structure. Cette notation peut tre simplifi e gr ce l'op rateur pointeur
de membre de structure, not >. L'expression pr c dente est strictement quivalente
p>membre
Ainsi, dans le programme pr c dent, on peut remplacer tab .nom et tab .date respectivement par
(tab + i)>nom et (tab + i)>date.
3.6.2 Structures auto r f renc es
On a souvent besoin en C de mod les de structure dont un des membres est un pointeur vers une
structure de m me mod le. Cette repr sentation permet en particulier de construire des listes cha n es.
En effet, il est possible de repr senter une liste d' l ments de m me type par un tableau (ou un
pointeur). Toutefois, cette repr sentation, dite contigu , impose que la taille maximale de la liste soit
connue a priori (on a besoin du nombre d' l ments du tableau lors de l'allocation dynamique). Pour
r soudre ce probl me, on utilise une repr sentation cha n e : l' l ment de base de la cha ne est une
structure appel e cellule qui contient la valeur d'un l ment de la liste et un pointeur sur l' l ment
suivant. Le dernier l ment pointe sur la liste vide NULL. La liste est alors d finie comme un pointeur
sur le premier l ment de la cha ne.
Pour repr senter une liste d'entiers sous forme cha n e, on cr e le mod le de structure cellule qui a
deux champs : un champ valeur de type int, et un champ suivant de type pointeur sur une struct
cellule. Une liste sera alors un objet de type pointeur sur une struct cellule. Gr ce au mot clef
typedef, on peut d finir le type liste, synonyme du type pointeur sur une struct cellule.
struct cellule
{
int valeur;
struct cellule *suivant;
};
typedef struct cellule *liste;
Un des avantages de la repr sentation cha n e est qu'il est tr s facile d'ins rer un l ment un endroit
quelconque de la liste. Ainsi, pour ins rer un l ment en t te de liste, on utilise la fonction suivante :
liste insere(int element, liste Q)
{
liste L;
L = (liste)malloc(sizeof(struct cellule));
L>valeur = element;
L>suivant = Q;
return(L);
}
Le programme suivant cr e une liste d'entiers et l'imprime l' cran :
#include <stdlib.h>
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html12/13#include <stdio.h>
struct cellule
{
int valeur;
struct cellule *suivant;
};
typedef struct cellule *liste;
liste insere(int element, liste Q)
{
liste L;
L = (liste)malloc(sizeof(struct cellule));
L>valeur = element;
L>suivant = Q;
return(L);
}
main()
{
liste L, P;
L = insere(1,insere(2,insere(3,insere(4,NULL))));
printf("\n impression de la liste:\n");
P = L;
while (P != NULL)
{
printf("%d \t",P>valeur);
P = P>suivant;
}
}
On utilisera galement une structure auto r f renc e pour cr er un arbre binaire :
struct noeud
{
int valeur;
struct noeud *fils_gauche;
struct noeud *fils_droit;
};
typedef struct noeud *arbre;
This document was translated from LATEX by HEVEA.
27/12/2014chapitre 3 : les pointeurshttps://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/chapitre3.html13/13