You are on page 1of 10

24- Notion de pointeur

Quest-ce quun pointeur ? Un pointeur est une variable qui contient une adresse mmoire. Un pointeur est une variable spciale qui peut contenir l'adresse d'une autre variable. Mmoire La mmoire est divise en emplacements numrots squentiellement. Chaque variable rside dans un emplacement unique en mmoire, connu par son adresse. Nous avons dj utilis loprateur & pour dsigner ladresse.
1

Dune manire gnrale, le langage C permet de manipuler des adresses par lintermdiaire de variables nommes pointeur . On dfinit une variable pointeur selon la syntaxe suivante: Type * nom_pointeur ; Une telle dfinition, dans sa structure correspond la dfinition dune variable. Elle contient le nom de la variable dfinir, qui est dans linstruction prcdente: nom_pointeur Ainsi que le type de cette variable pointeur, reprsenter par la spcification : Type.
2

Interprtation
Lindication de type comporte un nouveau lment, loprateur * que vous connaissez dj en tant quoprateur de multiplication. Cependant dans la dfinition dune variable pointeur, cet oprateur a une signification diffrente est un pointeur vers . Remarque : Les pointeurs et les noms de variables ont le mme rle: Ils donnent accs un emplacement dans la mmoire interne de l'ordinateur. Un pointeur est une variable qui peut 'pointer' sur diffrentes adresses. Le nom d'une variable reste toujours li la mme adresse.
3 4

Une dfinition telle que :

int *P ;

peut donc interprte comme: la variable P est un pointeur vers une donne de type int Ce qui quivaut : la variable dfinie P a le type int * Autre priphrase quivalente : la variable dfinie P peut mmoriser ladresse dune donne de type int . int A=10 ; P=&A ; /* P pointe sur A */

Interprtation
Pour accder aux donnes stockes ladresse dun pointeur, on utilise loprateur dindirection *. Il faut toujours initialiser lensemble des pointeurs dun programme avec une adresse existante ou la valeur nulle (0). float *a = 0; // 0 cest adresse

Exemple 1

Exemple 2
A B 4 C -2 -P1 0 P2 *P1 *P2 err err

Linstruction int * ad; rserve une variable nomme ad comme tant un pointeur vers des entiers. Loprateur * dsigne le contenu de ladresse ad. Lobjet dadresse ad est de type int; ce qui signifie bien que ad est ladresse dun entier. Linstruction ad=&n; affecte la variable ad la valeur et ladresse de la variable n. Linstruction *ad=m; affecte la valeur de m ad sans changer son adresse : implique n la valeur de m

Init. P1=&A P2=&C *P1=(*P2)++ P1=P2 P2=&B *P1-=*P2 ++*P2 *P1*=*P2 A=++*P2**P1 P1=&C *P2=*P1/=*P2

-2

&A

Exemple 2 (programme)

Exemple 2 (excution)

10

Exemple 3
Supposons que nous avons effectu ces dclarations : int * ad1, * ad2, * ad ; int n=10, p=20 ; Les variables ad1, ad2 et ad sont donc des pointeurs sur des entiers. Remarquez bien la forme de la dclaration, en particulier, si lon avait crit : int * ad1, ad2, ad ; La variable ad1 aurait bien t un pointeur sur un entier (puisque *ad1 est entier) mais ad2 et ad aurait t, quant eux des entiers.
11

Considrons maintenant ces instructions : ad1=&n; ad2=&p; *ad1 = * ad2 + 2; Les deux premires instructions placent dans ad1 et ad2 les adresses de n et p respectivement. La troisime instruction affecte * ad1 la valeur de lexpression * ad2 + 2.
12

13

14

Les oprations lmentaires sur pointeurs


Si un pointeur P pointe sur une variable X, alors *P peut tre utilis partout o on peut crire X.
int X, *P; P = &X;

24-1 Arithmtique des pointeurs


Jusquici, nous nous sommes content de manipuler, non pas les variables pointeurs elles mmes, mais les valeurs pointes. Or si une variable ad a t dclar ainsi: int * ad; une expression telle que: ad+1; ou ad+n; a un sens pour C. En effet, ad est cense contenir ladresse dun entier. Pour C, lexpression ci-dessus reprsente ladresse de lentier suivant. Dans cet exemple, cela na pas dintrt car nous ne savons pas avec certitude ce qui se trouve cet endroit. Mais nous verrons que cela savrera fort utile dans le traitement de tableaux ou de chanes.
15 16

les expressions suivantes, sont quivalentes:


Y = *P+1 *P = *P+10 *P += 2 ++*P P (*P)++ Y = X+1 X = X+10 X += 2 ++X &X X++

Exemple 1
Notez bien quil ne faut pas confondre un pointeur avec un nombre entier. En effet, lexpression ci-dessus ne reprsente pas ladresse de ad augmente de un (octet). Plus prcisment, la diffrence entre ad+1 est ad est ici de sizeof(int) octets. Loprateur sizeof fournit la taille en octets dun type donn. Si ad avait t dclar comme double: double * ad; Cette diffrence serait de sizeof(double) octets.

17

18

Exemple 2

19

20

24-2 Un nom dun tableau est un pointeur constant


En langage C, lidentificateur dun tableau, lorsquil est employ seul (sans indice sa suite) est considr comme un pointeur (constant) sur le dbut du tableau. Exemple : En effet, supposons, par exemple, que lon effectue la int t[10]; dclaration suivante: La notion t est totalement quivalente &t[0]. Lidentificateur t est considr comme tant de type pointeur sur le type correspondant aux lments du tableau, cest--dire, ici, int *. Ainsi, voici quelques exemple de notation quivalentes:
21

t+1 &t[1] t+i &t[i] t[i] *(t+i)


int A[10]; int *P;

l'instruction: P = A; est quivalente P = &A[0];

Pour illustrer ces nouvelles possibilits de notation, voici quelque exemples:


22

Exemple 1

Exemple 2

23

24

Exemple 3

Sans utiliser les oprateurs [ ], crire un programme qui lit et qui calcule le produit scalaire de deux vecteurs. Affichez les rsultats.
25 26

Sources d'erreurs
Un grand nombre d'erreurs lors de l'utilisation de C provient de la confusion entre soit contenu et adresse, soit pointeur et variable. Rsumons :
int A; //dclare une variable simple du type int A dsigne le contenu de A

Pointeurs et chanes de caractres


De la mme faon qu'un pointeur sur int peut contenir l'adresse d'un nombre isol ou d'une composante d'un tableau, un pointeur sur char peut pointer sur un caractre isol ou sur les lments d'un tableau de caractres. Un pointeur sur char peut en plus contenir l'adresse d'une chane de caractres constante et il peut mme tre initialis avec une telle adresse. Exemple : char *C; C = "Ceci est une chane de caractres constante";

&A dsigne l'adresse de A int B[10]; dclare un tableau de 10 lments de type int B &B[0] dsigne l'adresse de la premire composante de B. (Cette adresse est toujours constante) *(B+i) B[i] dsigne le contenu de la composante i du tableau B+i &B[i] dsigne l'adresse de la composante i du tableau

27

28

Pointeurs et chanes de caractres


Un pointeur sur char peut tre initialis lors de la dclaration si on lui affecte l'adresse d'une chane de caractres constante:
char *B = "Bonjour !";

Tableau de chanes

Attention ! Il existe une diffrence entre les deux dclarations:


char A[ ] = "Bonjour !"; /* un tableau */ char *B = "Bonjour !"; /* un pointeur */

A est un tableau qui a exactement la grandeur pour contenir la chane de caractres et la terminaison '\0'. Les caractres de la chane peuvent tre changs, mais le nom A va toujours pointer sur la mme adresse en mmoire. B est un pointeur qui est initialis de faon ce qu'il pointe sur une chane de caractres constante stocke quelque part en mmoire. Le pointeur peut tre modifi et pointer sur autre chose. La chane constante peut tre lue, copie ou affiche, mais pas modifie.
29 30

Pointeurs et tableaux deux dimensions


L'arithmtique des pointeurs se laisse largir avec toutes ses consquences sur les tableaux deux dimensions. Voyons cela sur un exemple : Le tableau M deux dimensions est dfini comme suit:
int M[4][10] = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},{10,11,12,13,14,15,16,17,18,19}, {20,21,22,23,24,25,26,27,28,29}, {30,31,32,33,34,35,36,37,38,39}}; Le nom du tableau M reprsente l'adresse du premier lment du tableau et pointe (oh, surprise...) sur le tableau M[0] qui a la valeur : {0,1,2,3,4,5,6,7,8,9}. L'expression (M+1) est l'adresse du deuxime lment du tableau et pointe sur M[1] qui a la valeur: {10,11,12,13,14,15,16,17,18,19}. et ainsi de suite. Au sens strict du terme, un tableau deux dimensions est un tableau unidimensionnel dont chaque composante est un tableau unidimensionnel. Ainsi, le premier lment de la matrice M est le vecteur {0,1,2,3,4,5,6,7,8,9}, le deuxime lment est {10,11,12,13,14,15,16,17,18,19} et ainsi de suite. L'arithmtique des pointeurs qui respecte automatiquement les dimensions des lments conclut logiquement que: M+I dsigne l'adresse du tableau M[I]
31

Pointeurs et tableaux deux dimensions


Problme : Comment pouvons-nous accder l'aide de pointeurs aux lments de chaque composante du tableau, c.-d.: aux lments M[0][0], M[0][1], ... , M[3][9] ? Solution 1:
int *P; int I, SOM; P = (int*)M; SOM = 0; for (I=0; I<40; I++) SOM += *(P+I);

Solution 2:
int I,J, SOM; SOM = 0; for (I=0; I<4; I++) for (J=0; J<10; J++) SOM += *(*M+I)+J);

Attention !

&M[i][j] *M+K avec K=i+j


32

Matrices et pointeur

Matrices et pointeur

33

34

Rsum
L'oprateur & permet de rcuprer l'adresse d'une valeur : si on a int a, alors &a dsigne l'adresse de la variable a. L'oprateur * permet de rcuprer la valeur pointe par une adresse si on a int *p, alors p est l'adresse de la variable et *p est sa valeur A un tableau d'un type quelconque i un indice pour les composantes de A A dsigne l'adresse de &A[0] ; A+i dsigne l'adresse de &A[i] *(A+i) dsigne le contenu de A[i] A+i dsigne l'adresse de la composante i du tableau *(A+i) dsigne le contenu de la composante i du tableau Si P = A, alors P pointe sur l'lment A[0] P+i *(P+i) pointe sur l'lment &A[i] dsigne le contenu de A[i]
35

Trouvez les erreurs dans les suites dinstruction suivantes : a) int *p , x = 34; *p = x; *p = x est incorrect parce que le pointeur p nest pas initialis b) int x = 17 , *p = x; *p = 17; *p = x est incorrect. Pour que p pointe sur x il faut faire : p = &x c) double *q; int x = 17 , *p = &x; q = p; q = p incorrect. q et p deux pointeurs sur des types diffrent d) int x, *p; &x = p; &x = p incorrect. &x nest pas une variable (lvalue) et par consquent ne peut pas figurer gauche dune affectation.
36

Comparaison
Faire un programme qui: 1- Dclare un tableau de cette manire: float T[5]={1,2,5,-2,5} ; 2- Dclare deux pointeurs P1 et P2 tels que pointe P1 sur le deuxime lment de T et P2 pointe sur le quatrime. 3- comparez P1 et P2. Afficherez leurs adresses dans un ordre dcroissant. 4- Affichez le tableau T (utilisez la notion pointeur).

On ne peut pas comparer que des pointeurs de mme type.


Exemple

37

38

Comparaison avec la valeur nulle


En principe, on ne peut comparer des pointeurs que sils sont de mme type. Cependant, tout pointeur (quel que soit son type) peut tre compar 0. Si p est un pointeur, une instruction comme: if(p==0) printf(" Erreur \n"); Est possible. Dans telle comparaison, on utilise pas la constante numrique 0, mais la constante symbolique NULL afin de faire ressortit quil sagit l dune comparaison de valeurs de pointeurs (donc adresses): if(p==NULL) printf(" Erreur \n"); La constante NULL est dfinie dans le header stdio.h.
39

You might also like