Telechargé par academic mail

pointeurs

publicité
Faculté des Sciences de Tunis
Leila Ben Othman
Programmation C
Première année LCE/LCS
Année universitaire: 2020 - 2021
Chapitre 6
Les pointeurs
Plan
1 Les pointeurs en C
Les opérateurs & et *
Opérations sur les pointeurs
Applications
2 Pointeurs et tableaux
3 Pointeurs et chaînes de caractères
4 Allocation dynamique de la mémoire
Les tableaux dynamiques
5 Pointeur et structures
Les pointeurs en C
Principe
Dénition
Un pointeur est une variable spéciale qui sert à contenir l'adresse
mémoire d'une autre variable.
• Accès direct à une variable
int X ;
X =2;
Pour modier a valeur de
X , on manipule directement la variable X .
• Accès indirect à une variable
X
int ;
=2;
(adresse de )
Pour manipuler , on manipulera
X
P
Leila Ben Othman, FST 2020-2021
X
X
4 / 33
P.
Les pointeurs en C
Déclaration
P
c
P
c
int * ; // On déclare un pointeur sur un entier
char * ; // On déclare un pointeur sur un caractère
• À la Déclaration, le pointeur ne pointe nulle part (sur rien)
⇒ P contient la valeur NULL ou la valeur numérique 0.
• Comparer P à 0 est possible car
• Pour acher le contenu de
P ==0 ⇔ P ==NULL.
P (pas très utile en pratique):
printf("Le contenu de P %p", P);
• Lorsque
P
contient la valeur NULL, le compilateur achera
sinon, il achera une valeur indiquant une adresse mémoire.
Leila Ben Othman, FST 2020-2021
5 / 33
nil,
Les pointeurs en C
Les opérateurs & et *
L'opérateur &: adresse de
x
x
int ; // On déclare un entier
int * ; // On déclare un pointeur sur un entier
=& ; // On indique que pointe sur la variable
P
P x
P
P
x
• L'opérateur & est l'opérateur d'adresse.
•
P =&x indique que P contient l'adresse de x .
•
P ne contient plus la valeur NULL, mais une adresse mémoire de la
variable x .
Leila Ben Othman, FST 2020-2021
6 / 33
Les pointeurs en C
Les opérateurs & et *
L'opérateur *: contenu de
• L'opérateur * indique le contenu de la variable pointée.
P
• * : indique le contenu de la variable pointée par
x
variable )
Exemple 1
int x,y;
int *P;
x=10;
P=&x;
*P=20;⇔ x=20
Leila Ben Othman, FST 2020-2021
7 / 33
P (ici, c'est la
Les pointeurs en C
Opérations sur les pointeurs
Aectation
Exemple 2
int *p1,*p2;
int x;
p1=&x;
p2=p1; // p1 et p2 pointent sur la même variable
: Toute modication du contenu de p1 entraîne une
modication du contenu de p2 puisqu'ils pointent sur la même variable.
Attention
Leila Ben Othman, FST 2020-2021
8 / 33
Les pointeurs en C
Opérations sur les pointeurs
Incrémentation/Décrémentation
Exemple 3
int *p;
int x;
p=&x;
p++; //
⇔
p=p+1 : p pointe sur l'entier suivant
p++/p- -: incrémente/décrémente l'adresse contenue dans p de manière
qu'elle désigne l'objet suivant/précédent. Ici, dans notre exemple, on
incrémente p pour pointer sur l'entier suivant (possible mais n'a pas un
intérêt sauf dans le cas de tableau ou de chaînes de caractères).
Leila Ben Othman, FST 2020-2021
9 / 33
Les pointeurs en C
Opérations sur les pointeurs
Comparaison
• On peut également comparer deux pointeurs (p1==p2, p1>p2),
sachant que p1 et p2 sont deux pointeurs sur des objets de même
type, avec les opérateurs : <, >, <=, >=, ==, !=.
• La comparaison de deux pointeurs qui pointent dans le même
tableau est équivalente à la comparaison des indices correspondants.
Si les pointeurs ne pointent pas dans le même tableau, alors le
résultat est donné selon leurs positions relatives dans la mémoire.
Leila Ben Othman, FST 2020-2021
10 / 33
Les pointeurs en C
Opérations sur les pointeurs
Priorités des opérateurs
• Les opérateurs * et & ont la même priorité que les opérateurs !,++
et (priorité de niveau 2). Dans une même expression, ces
opérateurs sont évalués de droite à gauche.
Exemple
int *p;
int x=5;
p=&x;
y=*p+5; // ⇔ y=x+5
*p=*p+6; // ⇔ x=x+6
*p+=4; // ⇔ x+=4
++*p; // ⇔ ++x
(*p)++; // ⇔ x++ 6= *(p++)⇔ *p++;
Leila Ben Othman, FST 2020-2021
11 / 33
Les pointeurs en C
Applications
Application 1
Somme de deux entiers avec les pointeurs
#include <s td i o . h>
v o i d main ( )
{
int a ,b , c ;
i n t ∗ p1 , ∗ p2 ;
p r i n t f ( " d o n n e r deux e n t i e r s " ) ;
s c a n f ( "%d%d" ,&a ,&b ) ;
p1=&a ;
p2=&b ;
// l a somme de deux e n t i e r s a v e c l e s p o i n t e u r s
c=∗ p1+∗ p2 ;
p r i n t f ( " l a somme e s t %d" , c ) ;
}
Leila Ben Othman, FST 2020-2021
12 / 33
Les pointeurs en C
Applications
Application 2
Permutation de deux entiers avec les pointeurs
#include <s td i o . h>
v o i d main ( )
{
int a ,b , c ;
i n t ∗ p1 , ∗ p2 ;
p r i n t f ( " d o n n e r deux e n t i e r s " ) ;
s c a n f ( "%d%d" ,&a ,&b ) ;
p1=&a ;
p2=&b ;
// p e r m u t a t i o n de deux e n t i e r s a v e c l e s p o i n t e u r s
c=∗ p1 ;
∗ p1=∗ p2 ;
∗ p2=c ;
p r i n t f ( " a=%d , b=%d" , a , b ) ;
}
Leila Ben Othman, FST 2020-2021
13 / 33
Pointeurs et tableaux
Pointeurs et tableaux (1)
• En C, le nom d'un tableau est
premier élément du tableau
•
•
•
un pointeur constant sur le
. On a donc les équivalences suivantes:
T[0]⇔ *T
T[1]⇔*(T+1)
T[i]⇔*(T+i)
• On a également les équivalences:
•
•
•
T ⇔ &T[0]
T+1⇔&T[1]
T+i⇔ &T[i]
Leila Ben Othman, FST 2020-2021
14 / 33
Pointeurs et tableaux
Pointeurs et tableaux (2)
• Comme le nom T d'un tableau est un pointeur constant, les
instructions suivantes sont donc
•
•
•
interdites
:
T++
T- -;
T=P (même si P est un pointeur sur un objet de même type que les
éléments de T)
• Pour parcourir un tableau, on peut utiliser un deuxième pointeur,
comme suit:
int T[10];
int *P;
P=T;
P++;
P- -;
Leila Ben Othman, FST 2020-2021
15 / 33
Pointeurs et tableaux
Application - Somme des éléments d'un tableau (1)
version 1
version 2
#include <s td i o . h>
#include <s td i o . h>
v o i d main ( )
{
i n t T[ 5 ] = { 2 , 4 , 1 , 1 3 , 1 0 } ;
i n t i , s =0;
f o r ( i =0; i <5; i ++)
s=s+T [ i ] ;
p r i n t f ( " l a somme e s t %d" , s ) ;
}
Leila Ben Othman, FST 2020-2021
16 / 33
v o i d main ( )
{
i n t T[ 5 ] = { 2 , 4 , 1 , 1 3 , 1 0 } ;
i n t s =0;
i n t ∗p ;
f o r ( p=T ; p<T+5; p++)
s=s +( ∗ p ) ;
p r i n t f ( " l a somme e s t %d" , s ) ;
}
Pointeurs et tableaux
Application - Somme des éléments d'un tableau (2)
version 3
#include <s td i o . h>
v o i d main ( )
{
i n t T[ 5 ] = { 2 , 4 , 1 , 1 3 , 1 0 } ;
i n t i , s =0;
f o r ( i =0; i <5; i ++)
s=s + ∗ (T+i ) ;
p r i n t f ( " l a somme e s t %d" , s ) ;
}
Leila Ben Othman, FST 2020-2021
17 / 33
Pointeurs et chaînes de caractères
Pointeurs et chaînes
Attention, ces deux déclarations sont diérentes:
1
char ch1[10]="Bonjour";// ch1 est un pointeur constant sur le
premier caractère de la chaîne.
2
char *ch2="Bonjour";// ch2 est un pointeur sur une chaîne
constante.
• Les instructions suivantes sont
interdites
ch1=ch2;
ch1++;
ch1=ch1+i;
ch2[0]='A';
• Les instructions suivantes sont permises:
ch1[0]='A';
ch2=@d'une autre chaîne;
ch2="Salut";
Leila Ben Othman, FST 2020-2021
18 / 33
:
Pointeurs et chaînes de caractères
Application - Parcours d'une chaîne (1)
version 1 - classique
#include <s td i o . h>
#include <s t r i n g . h>
v o i d main ( )
{
c h a r ch [ 1 0 ] = " B o n j o u r " ;
int
i =0;
f o r ( i =0; i <s t r l e n ( ch ) ; i ++)
p r i n t f ( "%c " , ch [ i ] ) ;
}
Leila Ben Othman, FST 2020-2021
19 / 33
Pointeurs et chaînes de caractères
Application - Parcours d'une chaîne (2)
version 2 - pointeurs
#include <s td i o . h>
#include <s t r i n g . h>
v o i d main ( )
{
c h a r ch [ 1 0 ] = " B o n j o u r " ;
c h a r ∗ pc ;
f o r ( pc=ch ; pc<ch+s t r l e n ( ch ) ; pc++)
p r i n t f ( " c=%c \n" , ∗ pc ) ;
}
Leila Ben Othman, FST 2020-2021
20 / 33
Pointeurs et chaînes de caractères
Application - Parcours d'une chaîne (3)
version 3 - pointeurs
#include <s td i o . h>
#include <s t r i n g . h>
v o i d main ( )
{
c h a r ch [ 1 0 ] = " B o n j o u r " ;
for ( int
i =0; i <s t r l e n ( ch ) ; i ++)
p r i n t f ( " c=%c \n" , ∗ ( ch+i ) ) ;
}
Leila Ben Othman, FST 2020-2021
21 / 33
Pointeurs et chaînes de caractères
Application - Parcours d'une chaîne (4)
version 4 - pointeurs
#include <s td i o . h>
#include <s t r i n g . h>
v o i d main ( )
{
c h a r ch [ 1 0 ] = " B o n j o u r " ;
int
i =0;
w h i l e ( ∗ ( ch+i )!= ' \0 ' )
{
p r i n t f ( "%c " , ∗ ( ch+i ) ) ;
i ++;
}
}
Leila Ben Othman, FST 2020-2021
22 / 33
Pointeurs et chaînes de caractères
Application - Parcours d'une chaîne (5)
version 5 - pointeurs
#include <s td i o . h>
#include <s t r i n g . h>
v o i d main ( )
{
c h a r ch [ 1 0 ] = " B o n j o u r " ;
c h a r ∗ pc ;
pc=ch ;
w h i l e ( ∗ pc != ' \0 ' )
{
p r i n t f ( "%c " , ∗ pc ) ;
pc++;
}
}
Leila Ben Othman, FST 2020-2021
23 / 33
Pointeurs et chaînes de caractères
Fonctions utiles sur les chaînes
1
La fonction strlen fournit en résultat la longueur d'une chaîne dont
on lui a transmis l'adresse en paramétre (sans compter le caractère
nul '\0' nal).
•
2
Exemple
strlen ("bonjour") vaudra 7;
char * adr = "salut"; l'expression strlen (adr) vaudra 5.
strcpy(dest,source): recopie la chaîne située à l'adresse source dans
l'emplacement d'adresse dest (y compris le '\0' nal). Il est
nécessaire que la taille du second emplacement soit susante pour
accueillir la chaîne à recopier.
•
Exemple
char source[10]="Bonjour";
char dest[10];
strcpy(dest,source);
Leila Ben Othman, FST 2020-2021
24 / 33
Pointeurs et chaînes de caractères
Fonctions utiles sur les chaînes
3
int strcmp (chaine1, chaine2): compare chaine1 à chaine2 et
retourne un entier:
• > 0 si chaine1 > chaine2
• 0 si chaine1==chaine2
• < 0 si chaine1 < chaine2
•
Exemple:
char *c1="Bonjour";
char c2[10]="Bonjour";
if (strcmp(chaine1, chaine2) == 0)
printf("Les deux chaînes sont identiques");
else
printf("Les deux chaînes sont diérentes");
Leila Ben Othman, FST 2020-2021
25 / 33
Pointeurs et chaînes de caractères
Fonctions utiles sur les chaînes
4
strcat(chaine1,chaine2) ajoute chaine2 à la n de chaine1.
•
Exemple
char ch1[10]="Bonjour";
char ch2[10]= " Monsieur";
printf("Avant strcat: %s",ch1); /*ch1 contient "Bonjour"*/
strcat(ch1,ch2);
printf("Après strcat: %s",ch1); /*ch1 contient "Bonjour
Monsieur"*/
Leila Ben Othman, FST 2020-2021
26 / 33
Allocation dynamique de la mémoire
Allocation dynamique (1)
•
Déclaration statique d'un tableau:
int T[10]={1,2,3,4,5}
⇒ ici, on réserve au moment de la déclaration de l'espace mémoire
pour stocker 10 entiers. (10*sizeof(int)) octets seront réservées pour
le stockage de T.
•
Inconvénients
•
•
•
•
:
Nous avons des données dont nous ne pouvons pas prévoir le nombre
et la grandeur lors de la programmation.
On ne peut plus ajouter des cases au tableau.
Réserver toujours l'espace maximal: du gaspillage de la mémoire. Il
nous faut donc un moyen de gérer la mémoire lors de l'exécution du
programme.
: Réservation de l'espace mémoire au moment de
l'exécution du programme et non pas au moment de la déclaration,
on parle d'Allocation dynamique de la mémoire.
Solution
Leila Ben Othman, FST 2020-2021
27 / 33
Allocation dynamique de la mémoire
Allocation dynamique (2)
• L'allocation dynamique désigne le fait qu'une variable est allouée
dynamiquement au cours de l'exécution du programme.
• Le langage C met à la disposition du développeur la fonction sizeof()
qui eectue le calcul de la taille nécessaire.
• Les fonctions de la gestion dynamique de la mémoire (malloc et
free) se trouvent dans la bibliothèque <stdlib.h>.
Leila Ben Othman, FST 2020-2021
28 / 33
Allocation dynamique de la mémoire
Allocation dynamique (3)
: l'allocation en C se fait à l'aide de la fonction malloc().
La fonction malloc de la bibliothèque <stdlib> nous aide à à
réserver de la mémoire au cours d'un programme.
•
Allocation
•
Syntaxe: malloc( <N> )
fournit l'adresse d'un bloc en mémoire de <N> octets libres ou la
valeur zéro s'il n'y a pas assez de mémoire.
•
Exemple
int * p ; //pointeur sur entier
p= malloc(sizeof(int)); //alloue un espace mémoire pouvant
contenir un entier et aecte son adresse à p.
•
Si nous voulons réserver de la mémoire pour des données d'un
type dont la grandeur varie d'une machine à l'autre, nous avons
besoin de la grandeur eective d'une donnée de ce type. L'opérateur
sizeof nous aide alors à préserver la portabilité du programme.
NB:
Leila Ben Othman, FST 2020-2021
29 / 33
Allocation dynamique de la mémoire
Allocation dynamique (3)
•
Libération: la libération d'un espace alloué se fait à l'aide de la
fonction free().
Exemple
...
free(p) ;
Leila Ben Othman, FST 2020-2021
30 / 33
Allocation dynamique de la mémoire
Les tableaux dynamiques
Tableaux dynamiques
v o i d main ( )
{
int n , i ;
i n t ∗T ;
p r i n t f ( " Donner n" ) ;
s c a n f ( "%d" ,&n ) ;
T=( i n t ∗ ) m a l l o c ( s i z e o f ( i n t ) ∗ n ) ;
f o r ( i =0; i <n ; i ++)
{
p r i n t f ( "T[%d]=" , i ) ;
s c a n f ( "%d" ,&T [ i ] ) ;
}
f o r ( i =0; i <n ; i ++)
p r i n t f ( " \nT[%d]=%d" , i , T [ i ] ) ;
f r e e (T ) ;
}
Leila Ben Othman, FST 2020-2021
31 / 33
Allocation dynamique de la mémoire
Les tableaux dynamiques
Tableaux dynamiques
Fonction qui permet de créer (dynamiquement) un tableau de n entiers et
le retourner.
int ∗ remplir_tab ( int n)
{ i n t ∗T , i ;
T=( i n t ∗ ) m a l l o c ( s i z e o f ( i n t ) ∗ n ) ;
f o r ( i =0; i <n ; i ++)
{
p r i n t f ( "T[%d]=" , i ) ;
s c a n f ( "%d" ,&T [ i ] ) ;
}
return T;
on ajoute un cast (int*) pour forcer le type de retour de malloc au
type du pointeur.
NB:
Leila Ben Othman, FST 2020-2021
32 / 33
Pointeur et structures
Pointeur et structures
struct personne
{
char nom[20] ;
int age;
};
• On déclare une variable de type pointeur vers une telle structure de
la manière suivante :
struct personne *p ;
•
Exemple
struct personne pers; // pers est une variable de type struct personne
struct personne *p; // p est un pointeur vers une struct personne
p = &pers;
(*p).age=20 ;// parenthèses obligatoires OU
p -> age=20 ; // -> opérateur d'accès
Leila Ben Othman, FST 2020-2021
33 / 33
Téléchargement