Structure de donnée
Tableau dynamique ou
pointeur
1
Pointeurs
On utilise des pointeurs dans :
La transmission des arguments par pointeurs (résultats de
retour)
La manipulation des tableaux
Etc.
2
Les Pointeurs en C
■ La déclaration de pointeurs
■ Valeurs pointées et adresses
■ Passage de paramètres de fonction par référence
■ Pointeurs et tableaux
3
Les pointeurs, c'est quoi?
Un pointeur est une variable particulière, dont la valeur est
l'adresse d'une autre variable.
■ Pointeur p: valeur 5A0F3 (adresse hexadécimale)
■ Adresse 5A0F3: valeur 17 (correspondant à la valeur d'un
entier i)
17
5A0F3
i=17
p=5A0F3
p i
Un pointeur est une adresse mémoire. On dit que le pointeur p pointe vers i,
puisque p pointe vers l’emplacement mémoire où est enregistrée i. 4
Les pointeurs: pourquoi ?
■ Les pointeurs sont nécessaires pour:
■ Efféctuer les appels par référence (i.e. écrire des fonctions qui
modifient certains de leurs paramètres)
■ Manipuler des structures de données dynamiques (liste, pile,
arbre,…)
■ Allouer dynamiquement de la place mémoire
5
Déclaration de Pointeurs
Le symbole * est utilisé entre le type et le nom du pointeur
❑ Déclaration d’un entier: int i;
❑ Déclaration d’un pointeur vers un entier: int *p;
Exemples de déclarations de pointeurs
int *pi; /* pi est un pointeur vers un int
*pi désigne le contenu de l'adresse */
float *pf; /* pf est un pointeur vers un float */
char c, d, *pc; /* c et d sont des char*/
/* pc est un pointeur vers un char */
double *pd, e, f; /* pd est un pointeur vers un double*/
/* e et f sont des doubles */
double **tab; /* tab est un pointeur pointant sur un pointeur qui
pointe sur un flottant double */
6
Opérateurs unaires pour manipuler les pointeurs,
& (adresse de) et * (contenu)
Exemple: int i = 8;
printf("VOICI i: %d\n",i);
printf("VOICI SON ADRESSE EN HEXADECIMAL: %p\n",&i);
nom_de_Pointeur = &nom_de_variable
void main(void)
p c
{ c.
char c = 'a', d = 'z'; te sur 0x1132 'a'
cpoin 0x1132
char*p; d o n
e c ; p
se d d
dre s
it l 'a 0x91A2 'z'
o *p = c;
p = &c;reç 0x91A2
printf("%c\n", *p);
p = &d; L’opérateur * (“valeur pointée par”)
printf("%c\n", *p);
}
7
#include <stdio.h>
void main() {
int *p, x, y;
p = &x; /* p pointe sur x */
x = 10; /* x vaut 10 */
y = *p - 1; printf(" y= *p - 1 =? = %d\n" , y);
*p += 1; printf(" *p += 1 =? *p = x= ? = %d %d\n" , *p, x);
y vaut ?
(*p)++; printf(" (*p)++ =? *p = x= ? = %d %d alors y=%d \n" , *p, x, y); x vaut ?
incrémente aussi de 1 la variable pointée par p, donc x vaut ??.
y vaut 9
*p=0; printf(" *p=0 x=? = %d\n" , x);
*p++; *p=20; printf(" *p++ x=? = %d\n" , x); comme p pointe sur x, maintenant x vaut ?
}
comme p ne pointe plus sur x, x vaut tjr ?
8
Operateurs * et ++
*p++ signifie:
*p++ trouver la valeur pointée
*p++ passer à l’adresse suivante
(*p)++ signifie: !
(*p)++ trouver la valeur pointée
(*p)++ incrémenter cette valeur (sans changer le pointeur)
*(p++) signifie:
*(p++) passer à l’adresse suivante
*(p++) trouver valeur de nouvellement pointée
*++p signifie:
*++p incrémenter d’abord le pointeur
*++p trouver la valeur pointée
9
Passage des paramètres par valeur et par adresse
Syntaxe qui conduit à une erreur: Syntaxe correcte:
a et b:
#include <stdio.h> #include
variables <stdio.h>
locales à
void ech(int x,int y) void ech(int *x,int *y)
{ { main(). La
int tampon; fonction ech
int tampon;
tampon = x; netampon
peut donc
= *x;
x = y; pas
*x modifier
= *y;
y = tampon; *y =valeur.
leur tampon;
} } On le fait
donc en
void main() void main()
passant par
{ {
int a = 5 , b = 8; l'adresse
int a = 5 , de
b=8;
ech(a,b); ces variables.
ech(&a,&b);
printf(“ a=%d\n ”, a) ; a = ? printf(“ a=%d\n ”, a) ; a=?
printf(“ b=%d\n ”, b) ; printf(“ b=%d\n ”, b) ; b=?
}
b =
}
?
PASSAGE DES PARAMETRES PASSAGE DES PARAMETRES
PAR VALEUR PAR ADRESSE 10
Passage de paramètres de fonction
par référence ou adresse
■ Quand on veut modifier la valeur void change ( int *a, int *b)
d'un paramètre dans une fonction, il {
faut passer ce paramètre par int tmp;
référence ou adresse tmp = *a;
*a = *b;
*b = tmp;
■ En C, cela se fait par pointeur }
11
Appel des fonctions par adresse
#include <stdio.h>
void change(int* p);
void main(void)
{
int var = 5;
change(&var);
printf("main: var = %d\n",var); !
}
void change(int* p)
{
*p *= 100;
printf("change: *p = %d\n",*p);
}
12
#include <stdio.h>
void somme(int , int , int *);
int modif(int , int *, int *);
void main(){
int a, b, c;
a = 2; b = 8;
somme(a, b, &c);
Somme de a=? et b=? :
printf("Somme de a=%d et b=%d : %d\n",a, b, c);
?
a = modif(a, &b, &c);
printf(" Modif : a=%d , b=%d et c= %d\n",a, b, c);
}
Modif : a=?, b=? et c=
void somme(int x, int y, int *z){
?
*z = x + y;
}
int modif(int x, int *y, int *z){
x *= 2; *y= x+ *y; *z= 5;
13
return x;
}
Identification des tableaux et pointeurs
■ En C, le nom d’un tableau représente l’adresse de sa
composante 0, donc a == &a[0]
■ C'est pour cela que les tableaux passés comme paramètres
dans une fonction sont modifiables
Passer des tableaux aux fonctions
■ Pour le compilateur, un tableau comme argument de fonction,
c’est un pointeur vers sa composante 0 (à la réservation mémoire près).
■ La fonction peut donc modifier n’importe quel élément (passage
par référence)
■ Le paramètre peut soit être déclaré comme tableau, soit comme
pointeur
int add_elements(int a[], int size) int add_elements(int *p, int size) 14
{ {
Utiliser des pointeurs - exemple
#include <stdio.h>
long sum(long*, int);
int main(void)
{
long Tab[6] = { 1, 2,
3, 5, 7, 11 };
printf("%ld\n", sum(Tab, 6));
return 0;
}
long sum(long *p, int sz)
{
long *end = p + sz;
long total = 0;
while(p < end)
total += *p++;
return total;
} 15