0% ont trouvé ce document utile (0 vote)
72 vues31 pages

Pointeurs en C : Concepts et Utilisation

Le chapitre 5 aborde les pointeurs en langage C, expliquant leur rôle en tant que variables contenant des adresses mémoire et leur utilisation pour accéder et manipuler des données. Il couvre également les concepts d'allocation dynamique de mémoire avec malloc et free, ainsi que l'interaction entre pointeurs et tableaux, y compris les tableaux à plusieurs dimensions et les chaînes de caractères. Des exemples pratiques illustrent comment déclarer, initialiser et utiliser des pointeurs dans divers contextes.

Transféré par

Emna Gammoudi
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)
72 vues31 pages

Pointeurs en C : Concepts et Utilisation

Le chapitre 5 aborde les pointeurs en langage C, expliquant leur rôle en tant que variables contenant des adresses mémoire et leur utilisation pour accéder et manipuler des données. Il couvre également les concepts d'allocation dynamique de mémoire avec malloc et free, ainsi que l'interaction entre pointeurs et tableaux, y compris les tableaux à plusieurs dimensions et les chaînes de caractères. Des exemples pratiques illustrent comment déclarer, initialiser et utiliser des pointeurs dans divers contextes.

Transféré par

Emna Gammoudi
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

Programmation C

Chapitre 5:

Les pointeurs

S.ELMANSOURI
2023-2024
Adresse mémoire
▪ Les informations, octets, int’s, chaînes sont stockées en mémoire.
→Sont enregistrées à un certain endroit de la mémoire : adresse.
▪ Adresse ≈ index de l’info dans le grand «tableau » de la mémoire.
Adresses et pointeurs
▪ Une adresse est une information comme une autre.
→ Besoin de la mémoriser, manipuler et d’accéder à son contenu.
▪ Pointeur : variable dont la valeur est une adresse.
▪ Variable pointée : variable dont l’adresse est contenue dans un pointeur.

▪ La variable pointée peut être de n’importe quel type : type simple, comme on l’a
déjà vu, mais aussi types complexes, ou même autres pointeurs.
→ Un pointeur est une adresse avec un type associé : le type des données
stockées à cette adresse.
Adresses et pointeurs
▪ Exemple:
Adresses et pointeurs
▪ Chaque variable possède une adresse.
▪ Obtenir l’adresse d’une variable : opérateur préfixe &.
▪ Accéder au contenu d’une adresse : opérateur préfixe *.

▪ & et * ont des rôles symétriques : *(&a) est la même chose que a.
Déclaration et initialisation
▪ On déclare un pointeur comme une variable classique, à l’exception du fait qu’on
fait précéder le nom de la variable de * :
▪ Exemple: char c = 4;
long x = 1234;
long *y;
▪ Pour utiliser le pointeur, il faut le faire pointer sur une adresse. Pour cela, on utilise
une expression appliquant l’opérateur & à une variable.
▪ Exemple, on peut faire pointer y sur x :
y = &x;

▪ On peut aussi utiliser un autre pointeur qui a déjà été initialisé.


▪ Exemple: on peut déclarer un nouveau pointeur z pointant sur la même adresse
que y, donc : x.
long *z = y;
Accès
▪ Une fois qu’un pointeur a été initialisé, l’opérateur * permet d’accéder à la valeur
contenue à l’adresse pointée.
▪ Exemple: afficher le contenu de la variable x en passant par les pointeurs y ou z :
//Les trois instructions affichent la même valeur 1234.
printf("contenu de x via x : %d",x);
printf("contenu de x via y : %d",*y);
printf("contenu de x via z : %d",*z);

▪ De la même façon, si on modifie la valeur contenue à l’adresse pointée, on modifie


la variable classique située à cette adresse.
▪ Exemple:
*y = 1000;
Exemple de manipulations de pointeurs
▪ Chaque case mémoire a une adresse.
▪ Par habitude et simplicité, adresses écrites en hexadécimal.
Exemple de manipulations de pointeurs
Exemple de manipulations de pointeurs
▪ c et d contiennent les adresses de b et a.
▪ Ils «pointent » vers b et a.
Exemple de manipulations de pointeurs
▪ On suit le pointeur dans c et on stocke 4 dans la case mémoire
correspondante → dans b.
Exemple de manipulations de pointeurs
▪ À gauche du “=” : case mémoire où ira le résultat.
▪ À droite du “=” : on évalue, i.e. on suit le pointeur c et on regarde ce qui est
dans la case.
Exemple de manipulations de pointeurs
▪ e pointe vers c.
Exemple de manipulations de pointeurs
▪ Double étoile : on suit deux pointeurs à la suite i.e. pointeur sur un pointeur.
Exemple de manipulations de pointeurs
▪ Deux pointeurs peuvent contenir la même adresse.
▪ On peut faire un test d’égalité dessus (c == d).
▪ On peut aussi comparer les contenus (*c == *d).
Allocation et libération
de mémoire
Statique versus dynamique
▪ Allocation statique : effectuée à la compilation.
▪ Ex : variables entières déclarées, tableaux de taille fixe :
▪ int v = 42 ;
▪ char s[10] ;
▪ Allocation statique locale : automatiquement libérée en fin de fonction.
▪ Allocation dynamique: On demande de la mémoire selon les besoins à
l’exécution.
▪ Zone allouée retournée désignée par son adresse de début.
Allocation dynamique
▪ La fonction malloc (memory allocation) permet d’allouer dynamiquement une
certaine quantité de mémoire. Son en-tête est la suivante :
void* malloc(int size)

➢ Argument : nombre d’octets demandés.


➢ Résultat : adresse du début de la zone octroyée.
➢ void* : pointeur sans type, implicitement compatible avec autres types de
pointeurs.
▪ Exemple: on veut allouer une zone de 3 entiers short
short *p;
p = (short*)malloc(3*sizeof(short));
//sizeof renvoie la taille en octets d’une donnée du type spécifié en paramètre
Allocation dynamique
▪ Si mémoire non disponible, résultat = pointeur NULL
→ Toujours tester la réussite de l’allocation !
▪ Exemple

short *p;
p = (short*)malloc(3*sizeof(short));
if(p == NULL)
// traitement de l’erreur
else
// traitement normal
Libération de mémoire
▪ La fonction free (memory allocation) permet permet de libérer une zone de
mémoire qui avait été allouée par malloc :
void free(void *p)

➢ Il suffit de passer en paramètre l’adresse de la zone à libérer. Ce paramètre


est de type void*, donc il peut s’agit de n’importe quel type de pointeur.
▪ Exemple:
free(p);
Pointeurs et tableaux
Pointeurs et tableaux à une dimension
▪ Tout tableau en C est en fait un pointeur constant.
int tab[10];

➢ tab est un pointeur constant (non modifiable) dont la valeur est l’adresse du
premier élément du tableau, i.e. tab ~&tab[0]
➢ On peut donc utiliser un pointeur initialisé a tab pour parcourir les éléments
du tableau.
▪ On accède à l’élément d’indice i du tableau tab grâce a l’operateur d’indexation
[], par l’expression tab[i].
▪ Cet operateur d’indexation peut en fait s’appliquer a tout objet p de type pointeur.
Il est lié à l’opérateur d’indirection * par la formule p[i] = *(p + i)
Pointeurs et tableaux à une dimension
▪ Exemple:
#define N 5
int tab[5] = {1, 2, 6, 0, 7};
main()
{
int i;
int *p;
p = tab;
for (i = 0; i < N; i++)
{
printf(" %d \n",*p);
//equivalent à:
//printf(" %d \n", p[i]);
p++;
}
}
Pointeurs et tableaux à une dimension
▪ La manipulation de tableaux, et non de pointeurs, possède certains inconvénients:
➢ on ne peut pas créer de tableaux dont la taille est une variable du programme,
➢ on ne peut pas créer de tableaux bidimensionnels dont les lignes n’ont pas
toutes le même nombre d’éléments.
▪ Ces opérations deviennent possibles dès que l’on manipule des pointeurs alloués
dynamiquement.
▪ Exemple: Pour créer un tableau d’entiers à n éléments où n est une variable du
programme: #include <stdlib.h>
main()
{
int n;
int *tab;
...
tab = (int*)malloc(n * sizeof(int));
...
free(tab);
}
Pointeurs et tableaux à plusieurs dimensions
▪ Un tableau à deux dimensions est, par définition, un tableau de tableaux. Il s’agit
donc en fait d’un pointeur vers un pointeur. Considérons le tableau à deux
dimensions défini par : int tab[M][N];
➢ tab est un pointeur, qui pointe vers un objet lui-même de type pointeur d’entier.
➢ tab a une valeur constante égale à l’adresse du premier élément du tableau,
&tab[0][0].
➢ De même tab[i], pour i entre 0 et M-1, est un pointeur constant vers un objet
de type entier, qui est le premier élément de la ligne d’indice i.
➢ tab[i] a donc une valeur constante qui est égale à &tab[i][0].
▪ On déclare un pointeur qui pointe sur un objet de type type * (deux dimensions)
de la même manière qu’un pointeur
type **nom-du-pointeur;
Pointeurs et tableaux à plusieurs dimensions
▪ Exemple:
main()
{
int k, n;
int **tab;
tab = (int**)malloc(k * sizeof(int*));

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


tab[i] = (int*)malloc(n * sizeof(int));
....
for (i = 0; i < k; i++)
free(tab[i]);

free(tab);
}
Pointeurs et tableaux à plusieurs dimensions
▪ Contrairement aux tableaux à deux dimensions, on peut choisir des tailles
différentes pour chacune des lignes tab[i].
▪ Exemple: si l’on veut que tab[i] contienne exactement i+1 éléments, on écrit:

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


tab[i] = (int*)malloc((i + 1) * sizeof(int));
Pointeurs et chaînes de caractères
Pointeurs et chaînes de caractères
▪ Une chaîne de caractères était un tableau à une dimension d’objets de type char,
se terminant par le caractère nul ’\0’
▪ On peut donc manipuler toute chaîne de caractères à l’aide d’un pointeur sur un
objet de type char.
▪ Exemple: La fonction strlen, définie dans la librairie standard string.h, donnant
la longueur d’une chaîne de caractères procède de manière suivante :
#include <stdio.h>
main()
{
int i;
char *chaine;
chaine = "Ceci est une chaine";
for (i = 0; *chaine != ’\0’; i++)
chaine++;
printf("nombre de caracteres = %d\n",i);
}
Pointeurs et chaînes de caractères
▪ Exemple: Créer une chaîne correspondant à la concaténation de deux chaînes de
caractères
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{ int i;
char *chaine1, *chaine2, *res, *p;
chaine1 = "chaine ";
chaine2 = "de caracteres";
res = (char*)malloc((strlen(chaine1) + strlen(chaine2)) * sizeof(char));
p = res; //utilisation d’un pointeur intermediaire p
/*sinon on aurait “perdu” la référence sur le premier caractère de la
Chaîne res.*/
for (i = 0; i < strlen(chaine1); i++)
*p++ = chaine1[i];
for (i = 0; i < strlen(chaine2); i++)
*p++ = chaine2[i];
printf("%s\n",res);
}
Questions?

Vous aimerez peut-être aussi