0% ont trouvé ce document utile (0 vote)
81 vues15 pages

Comprendre les pointeurs en C

Ce document décrit les pointeurs en C. Il explique le fonctionnement de la mémoire d'un ordinateur, la création et l'initialisation de pointeurs, les opérations sur les pointeurs, les pointeurs sur tableaux 1D et 2D, et l'allocation dynamique de mémoire avec malloc et free.

Transféré par

ouhssaineyoussef69
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
81 vues15 pages

Comprendre les pointeurs en C

Ce document décrit les pointeurs en C. Il explique le fonctionnement de la mémoire d'un ordinateur, la création et l'initialisation de pointeurs, les opérations sur les pointeurs, les pointeurs sur tableaux 1D et 2D, et l'allocation dynamique de mémoire avec malloc et free.

Transféré par

ouhssaineyoussef69
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

20/12/2020

Langage de programmation C

Chap. 05
Les pointeurs

a. Sabraoui Année universitAire 2020/2021

Sommaire

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

1
20/12/2020

La mémoire de votre ordinateur

La compréhension des pointeurs, repose sur le fonctionnement de


la mémoire 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

Mémoire(RAM) Adresses
var
1000
Processeur 100 1004
Bus 1008
1012
1016
1020
Un octet = 8 bits 1024

La mémoire de votre ordinateur

La mémoire vive 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
ordinateur.
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

2
20/12/2020

Création d’un pointeur

Dans la figure précédente nous avons déclaré une variable var


et nous l’avons initialisée à 100. Le compilateur a réservé un
emplacement mémoire à l’adresse 1004, qu’il associe au nom
de la variable.
L’adresse de cette variable var 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 var.

Création d’un pointeur

Soit p_var la variable dans laquelle on stockera l’adresse de var,


d’après le schéma ci-dessous un emplacement mémoire a été
réservé pour p_var
1001 1002 1003 1004 1005

? 100

p_var var

L’étape suivante consiste à stocker l’adresse de var dans la


variable p_var, celle-ci représente maintenant l’emplacement
mémoire de la variable var
1001 1002 1003 1004 1005

1004 100

p_var var

3
20/12/2020

Définition et déclaration

Définition
Un pointeur est une variable qui contient l'adresse d'une autre
variable.

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 de type int , ou bien p peut
contenir l'adresse d'une variable de type int
• *p est de type int, c’est l’emplacement mémoire pointé par p.

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;

4
20/12/2020

Initialisation

Exemple:
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

Exemples

Exemple 1:

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

5
20/12/2020

Exemples

Exemple 2:
#include <stdio.h>
#include <conio.h>
Void main( )
{
float a , *p; /*supposons que ces variables sont représentées en
mémoire à partir de l’adresse 1000*/
p = &a;
printf("Entrer une valeur : ");
scanf("%f" ,p); // on saisie la valeur 12.4
printf("\nAdresse de a = %d Contenu de a = %f",p,*p);
*p += 0.4;
printf("a = %f *p = %f ", a,*p);
}

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

6
20/12/2020

Opérations élémentaires sur les pointeurs

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 = &y;
t = NULL ; /* Correct */
t=0; /* Correct */
x=0;
t=x; /* Incorrect ! bien que x vaille 0 */
r = &x ;
t=r; /* Correct : p et r deux pointeurs de même type*/
t = pt ; /* Incorrect : p et pt deux pointeurs de type différent */

Exercices

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

1 int *p , x = 34; *p = x; *p = x est incorrect parce que le pointeur p n’est


pas initialisé

2 int x = 17 , *p = x; *p = 17; p = x est incorrect. Pour que p pointe sur x :


p = &x

3 double *q; int x = 17 , *p; q = p incorrect. q et p deux pointeurs sur des


p = &x; q =p; types différents

4 int x, *p; &x = p; &x = p incorrect. &x n’est pas une variable
(lvalue) et par conséquent ne peut pas figurer à
gauche d’une affectation.

7
20/12/2020

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.

Pointeurs et tableaux

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ères (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]

8
20/12/2020

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]
}

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

9
20/12/2020

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+i*N pointe sur A[i][0] et * ( p + i*N ) désigne A[i][0]
...
p+i*N+j pointe sur A[i][j] et * ( p + i*N +j) désigne A[i][j]
...
p + M*N-1 pointe sur A[M-1][N-1] et * ( p + M * N -1 ) désigne A[M-1][N-1]

Exemple

Lecture et Affichage d’une matrice matérialisée 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("%d", 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") ;
}
}

10
20/12/2020

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]

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.

11
20/12/2020

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.

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.

12
20/12/2020

Allocation dynamique
Fonction d’allocation dynamique de la mémoire

• Bibliothèque <stdlib.h>
void *malloc(taille) ; //allocation d’un bloc
void *calloc(taille, sizeof(type)) ; //allocation & initialisation d’un bloc
void *realloc(void *, taille); //modification de la taille d’un bloc
void free(void *) ; //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 renvoie:
⁃ L'adresse (non typée, void ∗) du bloc alloué s'il y a suffisamment
de mémoire disponible.

⁃ La valeur NULL en cas d'erreur (pas assez de mémoire libre).

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.

13
20/12/2020

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>

Allocation dynamique - exemple

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

14
20/12/2020

Allocation dynamique - exemple

Saisie et Affichage d’un tableau (suite):


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

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

15

Vous aimerez peut-être aussi