1 of 38

CHAPITRE 6�� LANGAGE DE � PROGRAMMATION: C

F. Karami

2 of 38

���� Les pointeurs

*

Programmer en langage C

2

3 of 38

Plan

1) Mémoire de l’ordinateur

2) Création, Définition, Déclaration et Initialisation d’un pointeur

3) Opérations élémentaires sur les pointeurs

4) Pointeurs et tableaux 1D et 2D

5) Arithmétiques des pointeurs

6) Allocation dynamique: Fonctions malloc et free

*

Programmer en langage C

3

4 of 38

1) La mémoire de votre ordinateur

  • La compréhension des pointeurs, repose sur le fonctionnement du mémoires de votre ordinateur.
  • Tout d’abord un bref rappel sur le fonctionnement des ordinateurs. Un ordinateur comporte un processeur et de la mémoire. Les deux sont connectés par un bus, c'est-à-dire un ensemble de lignes électriques

*

Programmer en langage C

4

Les pointeurs

1000

1004

1008

1009

1010

1014

1018

Bus

Processeur

Mémoire(RAM)

Adresses

Un octet = 8 bits

rate

100

5 of 38

  • La mémoire de votre ordinateur est constituée de milliers d’emplacements mémoire rangés de façon séquentielle. Chaque emplacement a une adresse unique, comprise entre 0 et une valeur maximale qui dépend de la quantité de mémoire installée sur votre ordinateurs.
  • Lorsqu’une variable est déclarée, le compilateur réserve un emplacement mémoire (une série de bits qu’on ne lit/écrit pas un par un mais par paquets de huit, ce que l'on appelle un octet (byte).) avec une adresse unique pour stocker cette variable(qu’on peut relire plus tard) .
  • Le compilateur associe l’adresse au nom de la variable. Quand le programme utilise le nom de la variable, il accède automatiquement à l’emplacement mémoire correspondant

*

Programmer en langage C

5

Les pointeurs

6 of 38

2) Création, Définition, Déclaration et Initialisation d’un pointeur�

  • Dans la figure précédente nous avons déclaré une variable rate et nous l’avons initialisé à 100. Le compilateur à réservé un emplacement mémoire à l’adresse 1004, qu’il associe au nom de la variable.
  • L’adresse de cette variable rate est un nombre, ce qui nous permet de l’utiliser comme n’importe quel autre nombre en langage C.
  • Si vous connaissez l’adresse d’une variable, vous pouvez créer une autre variable pour y stocker l’adresse de la première.
  • La première étape consiste à déclarer la variable dans laquelle on stockera l’adresse de rate.

*

Programmer en langage C

6

Les pointeurs

7 of 38

  • Soit p_rate la variable dans laquelle on stockera l’adresse de rate, d’après le schéma ci-dessous un emplacement mémoire a été réservé pour p_rate

  • L’étape suivante consiste à stocker l’adresse de rate dans la variable p_rate, celle-ci représente maintenant l’emplacement mémoire de la variable rate

*

Programmer en langage C

7

Les pointeurs

?

100

1001 1002 1003 1004 1005

p_rate

rate

1004

100

1001 1002 1003 1004 1005

p_rate

rate

8 of 38

Définition

  • Un pointeur est une variable qui contient l'adresse d'une autre variable.

*

Programmer en langage C

8

Les pointeurs

Déclaration

  • On déclare un pointeur par l’instruction :

type *nom_du_pointeur ;

    • Où: type est le type de la variable pointée,
    • l’identificateur nom_du_pointeur est le nom de la variable pointeur et * est l’opérateur qui indiquera au compilateur que c’est un pointeur.

 Exemple : int *p; float *p_float; char *p_char;

On dira que :p est un pointeur sur une variable du type int , ou bien p peut contenir l'adresse d'une variable du type int

*p est de type int, c’est l’emplacement mémoire pointé par p.

9 of 38

Initialisation

  • Déclarer un pointeur n’est pas suffisant, si vous ne le faites pas pointer sur une variable, il est inutile.

  • Un pointeur doit contenir l’adresse d’une variable en utilisant l’opérateur &, quand il est placé avant le nom de la variable, l’opérateur d’adresse renvoie l’adresse de cette variable.

Son initialisation est une instruction de la forme : pointeur=&variable;

*

Programmer en langage C

9

Les pointeurs

10 of 38

  • Exemple 1 :

    • int A, B, *P; /*supposons que ces variables occupent la mémoire à partir de l’adresse 1000 */
    • A = 10;
    • B = 50;
    • P = &A ; // se lit : mettre dans P l’adresse de A
    • B = *P ; /* se lit : mettre dans B le contenu de

la variable pointée par P */

    • *P = 20; /*mettre la valeur 20 dans la variable

pointé par P*/

    • P = &B; // P pointe sur B

*

Programmer en langage C

10

Les pointeurs

11 of 38

Exemple 1:

main(){

int v=12;

int u=10;

int *vP; /*pointeur sur int*/

vP = &v; /*affectation du pointeur */

u = *vP;

printf(“u=%d v=%d\n”,u,v);

*vP = 25;

printf(“u=%d v=%d\n”,u,v);

printf(“*vP=%d”,*vP);

}

*

Programmer en langage C

11

Les pointeurs

12 of 38

  • Explication de l’exemple 1

*

Programmer en langage C

12

Les pointeurs

13 of 38

Exemple 2 :

main( ){

float a , *ptr; /*supposons que ces variables sont représentées en

mémoire à partir de l’adresse 1000*/ clrscr( ); // pour effacer l’écran<conio.h>

ptr = &a;

printf(‘’Entrer une valeur : ‘’);

scanf(‘’%f’’ , ptr); // on saisie la valeur 12.4 

printf(‘’\n Adresse de a = %p Contenu de a = %f’’ ,ptr,*ptr);

*ptr += 0.4;

printf(‘’a = %f *p = %f ‘’, a,*ptr);

}

*

Programmer en langage C

13

Les pointeurs

14 of 38

3) Opérations élémentaires sur les pointeurs

  • L’opérateur & : ’adresse de’ : permet d’obtenir l’adresse d’une variable.
  • L’opérateur * : ’contenu de’ : permet d’accéder au contenu d’une adresse.
  • Si un pointeur P pointe sur une variable X, alors *P peut être utilisé partout où on peut écrire X.
  • Exemple :
    • int X=1, Y, *P; Après l’instruction P = &X ; On a :
    • Y = X + 1; équivalente à Y = *P + 1;
    • X += 2; équivalente à *P += 2;
    • ++X; équivalente à ++ *P;
    • X++; équivalente à (*P)++;

*

Programmer en langage C

14

Les pointeurs

15 of 38

  • Le seul entier qui puisse être affecté à un pointeur d’un type quelconque P est la constante entière 0 désignée par le symbole NULL défini dans <stddef.h>.
  • On dit alors que le pointeur P ne pointe ’nulle part’.

  • Exemple :

#include <stddef.h>

int *t, x , *r;

short y = 10 , *pt;

pt = &y;

t = NULL ; /* Correct */

t = 0 ; /* Correct */

x = 0 ;

t = x ; /* Incorrect ! bien que x vaille 0 */

r = &x ;

t = r ; /* Correct : t et r pointe sur des variables de même type*/

t = pt ; /* Incorrect : p et pt pointe sur des variable de type différent */

*

Programmer en langage C

15

Les pointeurs

16 of 38

Exercices

  • Trouvez les erreurs dans les suites d’instruction suivantes :

  1. int *p , x = 34;� *p = x;

b) int x = 17 , *p = x; �*p = 17;

c) double *q;� int x = 17 , *p;

p = &x; � q =p;

d) int x, *p; &x = p;

*

Programmer en langage C

16

Les pointeurs

17 of 38

Exercices

  • Trouvez les erreurs dans les suites d’instruction suivantes :

  1. int *p , x = 34; *p = x;

b) int x = 17 , *p = x; *p = 17;

c) double *q; int x = 17 , *p;

p = &x; q =p;

d) int x, *p; &x = p;

*

Programmer en langage C

17

Les pointeurs

  1. *p = x est incorrect parce que le pointeur p n’est pas initialisé

b) p = x est incorrect. Pour que p pointe sur x :p = &x

c) q = p incorrect. q et p deux

pointeurs sur des types différent

d)&x = p incorrect. &x n’est pas

une variable (lvalue) et par conséquent ne peut pas figurer à gauche d’une affectation.

18 of 38

4) Pointeurs et tableaux

  • En C, il existe une relation très étroite entre tableaux et pointeurs. Ainsi, chaque opération avec des indices de tableaux peut aussi être exprimée à l’aide de pointeurs. En effet, le nom d’un tableau représente l’adresse de son premier élément :
    • Tableau à une dimension (int T[N]) :
      • le nom T du tableau est un pointeur constant sur le premier élément (1er entier) du tableau
      • T et &T[0] contiennent l’adresse du premier élément (1er entier) du tableau.
    • Tableau à deux dimensions( int T[N][M]) :
      • le nom T est un pointeur constant sur le premier tableau d’entiers
      • T[i] est un pointeur constant sur le premier élément (1er entier) du ième tableau.
      • T et T[0] contiennent la même adresse mais leur manipulation n’est pas la même puisqu’ils ne représentent pas le même type de pointeur.

*

Programmer en langage C

18

Les pointeurs

19 of 38

  • Adressage et accès aux composantes d’un tableau à une dimension
    • En déclarant un tableau A de type int (int A[N]) et un pointeur P sur des variables entière (int *P), l’instruction P = A crée une liaison entre le pointeur P et le tableau A en mettent dans P l’adresse du premier élément de A (de même P = &A[0]).
    • A partir du moment où P = A, la manipulation du tableau A peut se faire par le biais du pointeur P. En effet
    • p pointe sur A[0] *p désigne A[0]
    • p+1 pointe sur A[1] *(p+1) désigne A[1]

...

    • p+(N-1) pointe sur A[N-1] *(p+N-1) désigne A[N-1]

*

Programmer en langage C

19

Les pointeurs

20 of 38

Exemple ( Lecture et Affichage d’un tableau matérialisé par un pointeur)

#include  <stdio.h>

#define N 10

main(){

float t[N] , *pt ;

int i ;

printf("Entrez %d entiers\n", N) ;

pt = &t[0] ; // ou pt = t

for (i = 0 ; i<N; i++)

scanf("%f", pt+i) ; // pt+i pointe sur t[i]

printf("\n Tableau lu : \n") ;

for (i = 0 ; i<N ; i++)

printf(« %f  », *(pt+i)) ; // *(pt+i) équivalente à t[i]

}

*

Programmer en langage C

20

Les pointeurs

21 of 38

Exemple ( Lecture et Affichage d’un tableau matérialisé par un pointeur)

/* Autre Solution sans déclarer la variable i */

#include <stdio.h>

#define N 10

main(){

float T[N] , *pt ;

printf("Entrez %d entiers\n", N) ;

for (pt = T ; pt<T+N; pt++)

scanf("%f", pt) ;

printf("\nTableau lu : \n") ;

for (pt = T ; pt<T+N; pt++)

printf("%7.2f", *pt) ;

}

*

Programmer en langage C

21

Les pointeurs

22 of 38

Pointeurs et tableaux à deux dimensions

  • En déclarant une matrice A de type int (int A[M][N]) et un pointeur P sur des variables entières (int *P),
  • l’instruction P = A[0] crée une liaison entre le pointeur P et la matrice A en mettent dans P l’adresse du premier élément de la première ligne de la matrice A ( P = &A[0][0]). A partir du moment où P = A[0], la manipulation de la matrice A peut se faire par le biais du pointeur P. En effet :

p pointe sur A[0][0] et * p désigne A[0][0]

p + 1 pointe sur A[0][1] et * ( p + 1 ) désigne A[0][1]

..

p + N pointe sur A[1][0] et * ( p + N ) désigne A[1][0]

p + N + 1 pointe sur A[1][1] et * ( p + N + 1 ) désigne A[1][1]

..

p + M * N-1 pointe sur A[M-1][N-1] et * ( p + M * N -1 ) désigne A[M-1][N-1]

*

Programmer en langage C

22

Les pointeurs

23 of 38

Exemple ( Lecture et Affichage d’une matrice matérialisé par un pointeur)

#define M 4

#define N 10

main(){

short A[M][N] ;

short *pt ;

int i, j ;

/* lecture d’une matrice */

pt = &A[0][0] ; /* ou bien pt = A[0] ; */

for (i = 0 ; i<M ; i++){

printf("\t ligne n° %d\n", i+1) ;

for (j = 0 ; j<N ; j++)

scanf("%i", pt + i * N + j ) ;

}

/* affichage d’une matrice */

for (i = 0 ; i<M ; i++) {

for (j = 0 ; j<N ; j++)

printf("%d", *( pt + i * N + j ) ) ;

printf("\n") ; }}

*

Programmer en langage C

23

Les pointeurs

24 of 38

5) Arithmétiques des pointeurs

  • Affectation par un pointeur sur le même type :
    • Soient P1 et P2 deux pointeurs sur le même type de données.
    • L’affectation : P1 = P2 ; fait pointer P1 sur le même objet que P2.�
  • Addition et soustraction d’un nombre entier :
    • Si P pointe sur l’élément A[i] d’un tableau, alors :
    • P+n pointe sur A[i+n] et P-n pointe sur A[i-n]

*

Programmer en langage C

24

Les pointeurs

25 of 38

Arithmétiques des pointeurs

  • Incrémentation et décrémentation d’un pointeur :
    • Si P pointe sur l’élément A[i] d’un tableau, alors après l’instruction :
    • P++ ; P pointe sur A[i+1]
    • P += n ; P pointe sur A[i+n]
    • P-- ; P pointe sur A[i-1]
    • P -= n ; P pointe sur A[i-n]
  • Comparaison de deux pointeurs :
    • On peut comparer deux pointeurs de même type par : <, >, <=, >=, == ou !=
    • La comparaison de deux pointeurs qui pointent dans le même tableau est équivalente à la comparaison des indices correspondants.

*

Programmer en langage C

25

Les pointeurs

26 of 38

Autres déclarations des pointeurs :

  • En C, il existe d’autres déclarations des pointeurs. En effet :
  • Tableau de pointeurs :
    • int *Tab[20] ;
    • déclare un tableau Tab de 20 pointeurs d’entiers.
  • Pointeur de tableaux :
    • int (*pt)[30] ;
    • déclare un pointeur pt sur des tableaux de 30 composantes.
  • Pointeur de pointeurs :
    • int **pt ;
    • déclare un pointeur pt qui pointe sur des pointeurs d’entiers.

*

Programmer en langage C

26

Les pointeurs

27 of 38

Allocation dynamique

  • La déclaration d’un tableau définit un tableau statique  (il possède un nombre figé d’emplacements). Il y a donc un gaspillage d’espace mémoire en réservant toujours l’espace maximal prévisible.

  • Il serait souhaitable que l’allocation de la mémoire dépend du nombre d’éléments à saisir. Ce nombre ne sera connu qu’à l’exécution :

c’est l’allocation dynamique.

*

Programmer en langage C

27

Les pointeurs

28 of 38

  • Fonction d’allocation dynamique de la mémoire
    • Bibliothèque <stdlib.h>�
      • char *malloc(taille) ; //allocation d’un bloc
      • char *calloc(taille, sizeof(type)) ;//allocation & initialisation d’un bloc
      • char *realloc(char *, taille); //modification de la taille d’un bloc
      • void free(char *) ; //libération d’un bloc
    • Chacune des fonctions malloc, calloc ou realloc, prend une zone d’une taille donnée dans l’espace mémoire libre réservé pour le programme (appelé tas ou heap) et affecte l’adresse du début de la zone à une variable pointeur.
    • S’il n’y a pas assez de mémoire libre à allouer, la fonction renvoie le pointeur NULL.

*

Programmer en langage C

28

Les pointeurs

29 of 38

Fonctions malloc et free

  • malloc

    • <pointeur> = <type> malloc(<taille>);
      • <type> est un type pointeur définissant la variable pointé par <pointeur>
      • <taille> est la taille, en octets, de la zone mémoire à allouer dynamiquement, <taille> est du type unsigned int, donc on ne peut pas réserver plus de 65536 octets à la fois

    • La fonction malloc retourne l’adresse du premier octet de la zone mémoire allouée. En cas d’échec, elle retourne NULL.

*

Programmer en langage C

29

Les pointeurs

30 of 38

Fonctions malloc et free

  • free

    • Si on n’a plus besoin d’un bloc de mémoire réservé dynamiquement par malloc, alors on peut le libérer à l’aide de la fonction free.

    • free(<pointeur>);

    • Libère le bloc de mémoire désigné par le pointeur <pointeur>

*

Programmer en langage C

30

Les pointeurs

31 of 38

Exemple (Allocation dynamique, Saisie et Affichage d’un tableau )

#include <stdio.h>

#include <stdlib.h>

main(){

short *pt;

int N , i;

printf("Entrez la taille N du tableau \n") ;

scanf("%d", &N) ;

pt = ( short * ) malloc( N * sizeof( short ) );

if (pt == NULL)

printf("Mémoire non disponible") ;

*

Programmer en langage C

31

Les pointeurs

32 of 38

Exemple (Allocation dynamique, Saisie et Affichage d’un tableau )

printf("Saisie du tableau : ");

for ( i = 0 ; i < N; i++)

scanf("%d", pt + i ) ;

printf("Affichage du tableau ") ;

for ( i= 0 ; i < N; i++)

printf("%d\t", *( pt + i ) ) ;

free( pt );

}

*

Programmer en langage C

32

Les pointeurs

33 of 38

  • Gestion dynamique des tableaux
    • EXEMPLE :�

/* Déclaration d'un pointeur sur des entiers p et de la taille du tableau N */

int* p=NULL;

int N;

/* Saisie de la taille du tableau par l'utilisateur */

scanf ("%d",&N);

/* Allocation dynamique de la zone mémoire occupée par le tableau */

p = (int*)malloc (N*sizeof(int));

*

Programmer en langage C

33

Les pointeurs

34 of 38

Pointeurs et structures

  • Les pointeurs membres d’une structure
    • Un pointeur qui est membre d’une structure se déclare de la même façon qu’un pointeur qui ne l’est pas, en utilisant l’opérateur indirect(*), exemple:

Struct data {

int *valeur;

int *taux;

} premier;

    • Soit cout et interet de variable de type int tel que :
      • int cout, interet;
    • L’initialisation du pointeur valeur et taux suit la syntaxe suivante :
      • premier.valeur=&cout;// (*premier.valeur=cout;)
      • premier.taux=&interet; // (*premier.taux=interet;)

*

Programmer en langage C

34

Les pointeurs

35 of 38

Pointeurs et structures

  • Les pointeurs vers une structure
    • Soit la structure personne définie par:

struct point{

int num;

float x;

float y;

};

    • On déclarera une variable de type pointeur vers cette structure de la façon suivante :
      • struct point *p;
    • Pour initialiser ce pointeur, il faut déclarer une structure sur le modèle struct point, sur laquelle il va pointer :
      • struct point pnt;
      • p=&pnt;

*

Programmer en langage C

35

Les pointeurs

36 of 38

Pointeurs et structures

  • Les pointeurs vers une structure
    • Pour accéder aux membres de la structure point, on utilise soit l’opérateur (.) :
      • (*p).num=1;
      • (*p).x=1.2;
      • (*p).y=2.5;�
    • soit (->) comme suit:
      • p ->num=1;
      • p ->x=1.2;
      • p ->y=2.5;

*

Programmer en langage C

36

Les pointeurs

37 of 38

Pointeurs et structures

  • Pointeurs et tableaux de structures
    • Soit la structure définie par:
        • struct part{

int nombre;

char nom[10];

};

Nous pouvons déclarer un tableau appartenant au type part

      • struct part data[50];

Nous pouvons ensuite déclarer un pointeur vers une structure de

type part, et l’initialiser pour pointer sur la première structure du

tableau data:

      • struct part *p_part;
      • p_part=&data[0];// ou bien écrire p_part=data;

Nous obtenons un tableau de structures de type part et un pointeur

vers le premier élément du tableau. On affiche le contenu du premier

élément avec l’instruction:

        • printf(’’ %d %s ’’, p_part->nombre , p_part ->nom);

*

Programmer en langage C

37

Les pointeurs

38 of 38

Pointeurs et structures

  • Pointeurs et tableaux de structures :exemple

#include<stdio.h>

#define max 4

struct part{

int nombre;

char nom[10];

}data[Max]={1,’’smith’’, 2, ‘’jones’’, 3, ‘’Adams’’, 4,’’Wilson’’};

struct part *p_part;

int count;

main(){

P_part=data;

for(count=0; count<Max ; count++){

printf(‘’A l’adresse %d : %d %s\n’’,p_part,(p_part+count)->nombre, ,(p_part+count)->nom);

// p_part++;

}

}

*

Programmer en langage C

38

Les pointeurs