Chapitre 3 : Les pointeurs

Computer Science - C Programming · course

Voir tous les documents en programmation

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