Les pointeurs et
l’allocation dynamique de é
mémoire
Thèmes abordés
• Compléments sur les pointeurs
– Rappels – Rappels
– Déclaration de types pointeurs – Opérateurs
– Les pointeurs et les tableaux – Recommandations
• Allocation dynamique de mémoire
– Principes.
é
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 1
– Allocation et libération.
– Variables simples, tableaux, structures.
– Allocation dynamique et transtypage de pointeurs.
– Les fuites de mémoire.
– Quelques fonctions de manipulation de mémoire
Définition - Rappel
• Un pointeur
C’est ne ariable o ne constante – C’est une variable ou une constante.
– Désignant l’emplacement d’une variable en mémoire.
– C’est un nombre entier contenant l’adresse de la variable.
– Le pointeur désigne ou « pointe » sur la variable.
A010
ppi
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 2
A000 A004 A008
i j
A00C
k pi
int i, j, k;
int* pi = &i; // pi contient A000 int** ppi = π // ppi contient A00C
Les pointeurs
Déclaration
• Forme générale type* var;
• Déclarations combinées
int i, j, k, * pi, ** ppi;
• Un pointeur peut pointer
– Une variable ou constante de n’importe quel type de données Si l i l d bl
i, j, k : de type int pi de type int*
ppi de type int**
• Simple : int, long, double, …
• Composé : tableau, struct, union.
• Pointeur.
Représentation en mémoire
• Un pointeur est un entier.
– Contenant l’adresse de la variable pointée.p – Sa taille dépend du microprocesseur.
• Comment varie la taille en mémoire d’un pointeur en fonction du type pointé ?
char * pchar;
int * pint;
double * pdouble;
i tf(" h %d\ " i f( h ))
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 4
printf("pchar:%d\n", sizeof(pchar));
printf("pint:%d\n", sizeof(pint));
printf("pdouble:%d\n", sizeof(pdouble));
– Sur PC sous Win32 : toujours 32 bits.
– Sur PC sous Win64 : toujours 64 bits.
Les pointeurs
Opérateurs de base
• Récupération d’adresse – Rappel : pp
• l’opérateur &placé devant une variable renvoie son adresse.
• Déréférencement – Rappel :
• l’opérateur *placé devant un pointeur permet de désigner la variable pointée.
• Quel est l’effet de :
int i, *pi;
pi &i
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 5
pi = &i;
i = 1;
*pi = 2;
*&i = 3;
pi = 4;
*pi = 5;
Somme d’un pointeur et d’un entier
• Somme d’un pointeur et d’un entier
– Lorsqu’on ajoute 1 à un pointeur, cela augmente la valeur de l’adresse
’il ti t d 1 i d l t ill d’ élé t i té qu’il contient non pas de 1, mais de la taille d’un élément pointé.
– Intérêt :
• Si un pointeur pointe au début d’un tableau.
• Ajouter 1 fait pointer sur l’élément suivant.
• Exemple
int tab[4] = {0, 10, 20, 30};
int* t;
t = &tab[0]; A000
A004 A008
tab[0]
tab[1]
A00C
tab[2]
tab[3]
A010
t
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 6
printf("%d\n", *t);
t = t + 1;
printf("%d\n", *t);
t = t + 1;
printf("%d\n", *t);
t = t + 1;
printf("%d\n", *t);
A000
tab[0]
Les pointeurs
Somme d’un pointeur et d’un entier
• Exemple
A008
A00C
x
A00C
px
int i, *pi;
double x, *px;
pi = &i;
printf("pi :%d\n", pi);
pi = pi + 1;
printf("pi+1 :%d\n" pi);
A000 A004 A008
i pi
printf( pi+1 :%d\n , pi);
px = &x;
printf("px :%d\n", px);
px = px + 1;
printf("px+1 :%d\n", px);
Somme d’un pointeur et d’un entier
• Somme d’un pointeur et d’un entier
– Lorsqu’on ajoute « n » à un pointeur cela augmente la valeur de – Lorsqu on ajoute « n » à un pointeur, cela augmente la valeur de
l’adresse de « n » fois la taille d’un élément pointé.
– Si le pointeur pointe vers un tableau, il pointe ensuite sur l’élément situé n éléments plus loin
• Différence d’un pointeur et d’un entier
– Fonctionne comme la somme, mais soustrait le décalage.
• Opérateurs combinés
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 8
+=
-=
• Opérateurs d’incrémentation et de décrémentation
++ : le pointeur pointe sur l’élément suivant.
-- : le pointeur pointe sur l’élément précédent.
Les pointeurs
Exemple : itération sur un tableau avec un pointeur.
void afficher(char chaine[]) {
{
char * tmp;
tmp = &chaine[0];
while (*tmp != '\0') {
putchar(*tmp);
tmp++;
}
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 9
} }
Et les tableaux
• Rappel
Le nom d’ n tablea désigne son adresse – Le nom d’un tableau désigne son adresse.
• Pointeur sur le premier octet du premier élément du tableau.
– On peut passer un tableau en paramètre sous la forme d’un pointeur.
• En C
– Les tableaux et les pointeurs désignent une adresse.
– Les opérateurs des tableaux s’appliquent aux pointeurs.
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 10
Les opérateurs des tableaux s appliquent aux pointeurs.
– On peut indicer un pointeur avec [].
– On peut affecter un pointeur directement avec l’adresse d’un tableau.
Les pointeurs
Et les tableaux
void afficher(char chaine[]) {
{
char * tmp;
tmp = chaine; // cette affectation est valide while (*tmp != '\0')
{
putchar(tmp[0]); // tmp[0] équivalent à *tmp tmp++;
} } }
// Autre forme possible pour le prototype void afficher(char * chaine)
. . .
Somme et différence de 2 pointeurs
• Somme de 2 pointeurs – Cette opération est invalide.p – Refusée à la compilation.
• Différence de 2 pointeurs – Cette opération est valide.
– Elle renvoie la différence entre les 2 adresses.
– Exprimée en multiple du nombre d’éléments du type pointé.
• Exemple int tab[50];
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 12
int * t1, * t2;
t1 = &tab[0];
t2 = &tab[1];
printf("%d\n", t2 - t1); // Affiche 1
Les pointeurs
Pointeurs non typés
• Un pointeur désigne une adresse.
• Dans certaines circonstances, on veut – Manipuler une adresse.
– Sans indiquer le type des éléments pointés.
• Pointeur non typé
– Le langage C permet de manipuler des pointeurs non typés.
• Syntaxe
void* pointeur;
int i;
double x;
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 13
pointeur = &i;
pointeur = &x;
• Exemple
int fread(void* buffer, int size, int count, FILE* file);
• Restriction
– Un pointeur non typé ne peut pas être déréférencé avec *
Transtypage
• Un pointeur void * est inutilisable.
Po r lire o écrire ce q i est pointé il fa t préciser le t pe des – Pour lire ou écrire ce qui est pointé, il faut préciser le type des
éléments pointés.
– On change le type du pointeur par transtypage (type cast).
• Effet
– L’adresse reste inchangée.
– Le type des éléments pointés devient connu.
– On peut alors déréférencer le pointeur transtypé
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 14
On peut alors déréférencer le pointeur transtypé.
• Le transtypage est possible
– Entre tous les types de pointeurs.
– Il est aussi possible de transtyper un entier en pointeur et vice versa.
Les pointeurs
Transtypage
#include<stdio.h>
void mettre a zero(void_ _ * memoire, intnombre octets)_ {
inti;
char* memoire_char;
memoire_char = (char*)memoire;
for(i = 0; i < nombre_octets; i++) memoire_char[i] = 0;
}
intmain(intargc, char* argv[]) {
inti;
inti;
double x[100];
mettre_a_zero(&i, sizeof(i));
mettre_a_zero(&x, sizeof(x));
printf("Pressez une touche...");
_getch();
}
Utilisations originales – différentes vues du contenu de la mémoire
• Quels sont les octets constituant un entier 32 bits ?
longl;
unsigned char * pointeur;
l = 0xABCDEF12;
pointeur = &l;
printf("%02x, %02x, %02x, %02x\n", pointeur[0], pointeur[1], pointeur[2], pointeur[3]);
• Explication
– La même adresse peut être vue comme :
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 16
• Un long
• Un tableau de char – Sur ce processeur
• Le tableau commence par le « petit morceau »
• En anglais, little end.
• On parle de processeur travaillant en « Little Endian »
A000
12
A004
ef cd ab
A000 A001 A002 A003
Les pointeurs
Utilisations originales – les adresses absolues
• Sur les micro contrôleurs
Il a des registres po r tiliser les périphériq es – Il y a des registres pour utiliser les périphériques.
– Exemple : registre pour fixer l’état de sorties tout ou rien.
– Ces registres se trouvent à des adresses fixes. Exemple : 0x00F3
• Comment faire pour écrire l’octet 0x12 à cette adresse ?
*((char *)0x00F3) = 0x12; 1. Transtypage de 0x00F3 en pointeur sur char.
2. Déréférencement pour accéder à ce qui est pointé, soit le registre situé en 0X00F3.
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 17
NULL
• L’adresse 0
S r de nombre s stèmes l’adresse 0 est in alide o réser ée – Sur de nombreux systèmes, l’adresse 0 est invalide ou réservée.
– Un programme applicatif n’utilise donc jamais cette adresse.
– On l’utilise pour dénoter un pointeur vide ou invalide.
• Utilisation
– On peut ainsi tester si une adresse est valide en comparant avec 0.
if (pointeur == 0) ou if (pointeur != 0)
En général on utilise plutôt la constante symbolique NULL
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 18
• En général, on utilise plutôt la constante symbolique NULL
– Définie dans stdio.h
#define NULL ((void *)0) – Ce qui donne
if (pointeur == NULL) ou if (pointeur != NULL)
Les pointeurs
Passage en paramètre par valeur
• Un pointeur peut être passé en paramètre par valeur
E emple : la fonction printf – Exemple : la fonction printf
int printf(const char * format, ...);
– Comme pour tout paramètre, la valeur est copiée dans le paramètre formel.
– Simplement, dans ce cas, la valeur est une adresse.
Passage en paramètre par adresse
• Un pointeur peut être passé en paramètre par adresse !
E emple – Exemple
void message_erreur(int code, char** message);
– Le paramètre message est de type
• pointeur sur un pointeur de caractères.
• Dit de façon plus compréhensible : pointeur sur une chaîne de caractères.
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 20
Les pointeurs
Passage en paramètre par adresse
#include<stdio.h>
typedef enum{ ok, erreur_simple, erreur_fatale } type_erreur;
voidmessage_erreur(type_erreur code, char** message) {
switch(code) {
caseok:
*message = "Ok";
break;
caseerreur_simple:
*message = "Erreur simple";
break;
caseerreur_fatale:
*message = "Erreur fatale";
break;
default:
*message ="Erreur inattendue";
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 21
message Erreur inattendue; break;
} } intmain() {
char* msg;
message_erreur(erreur_fatale, &msg);
puts(msg);
printf("Pressez une touche...");
_getch();
}
Définition de types pointeur
• Constat
– Les pointeurs sur des pointeurs sont peu lisibles.
– Alternative : créer un type pointeur plus explicite
On reconnait un paramètre de type string passé par adresse.
Alternative : créer un type pointeur plus explicite.
• Exemple
typedef char* string;
void message_erreur(type_erreur code, string* message) {
. . .
*message = "Ok";
. . . }
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 22
int main(int argc, char* argv[]) {
string msg;
message_erreur(erreur_fatale, &msg);
puts(msg);
printf("Pressez une touche...");
_getch();
}
Rappel : variables allouées sur la pile
• Création de variables locales
Les ariables locales et les paramètres sont placés s r la pile à – Les variables locales et les paramètres sont placés sur la pile à
l’entrée d’une fonction.
– Elles sont automatiquement libérées à la sortie de la fonction.
12345
12345
12345
A014 pointeur de pile A010A010
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 24
pointeur de pile
0x103DAF93 3.14159f 2.718281828459
A000 A004 A008 A010 A00C A010
Limitations avec les variables de pile
1. Taille fixe des résultats
• La taille maximale des variables doit être connue à l’avance
l avance
– Exemple : gets
char ligne[80]; // ne dépend pas de la longueur du texte saisi gets(char);
• Comment écrire une fonction renvoyant un résultat dont la taille n’est connue qu’à l’exécution ?
// le résultat dépend nécessairement de la taille du fichier
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 25
char * lire_fichier_texte(const char * nom_fichier);
2. Impossibilité de retourner un tableau créé par une fonction
#define MAX_POINT 1000
double* generer_sinus(double amplitude, int nombre_points) {
double valeurs[MAX_POINT]; //réserver suffisamment d'espace int i;
if (nombre_points < MAX_POINT) {
for (i = 0; i < nombre_points; i++)
valeurs[i] = amplitude * sin(i * 2 * M_PI / nombre points);
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 26
Retourne l’adresse d’un tableau situé sur la pile.
La mémoire utilisée sera recouverte par les prochaines valeurs placées sur la pile ! nombre_points);
return valeurs;
} else
return NULL;
}
Allocation dynamique de mémoire
Principe
• Exploitation de la mémoire disponible
La pile n’occ pe q ’ ne partie de la mémoire – La pile n’occupe qu’une partie de la mémoire
– La mémoire restante peut aussi être exploitée par programme.
– On appelle cette zone le « tas », « heap » en anglais.
pile
tas
Principe
• Le tas permet
D’allo er des blocs de mémoire po r le programme – D’allouer des blocs de mémoire pour le programme.
– De les libérer lorsqu’ils ne sont plus utilisés.
– Il peut alors y avoir fragmentation de la mémoire.
pile
Bloc 1 / 1000 octets
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 28
tas
Bloc 2 / 500 octets Bloc 3 / 1000 octets
Bloc 4 / 1000 octets
Allocation dynamique de mémoire
Allocation – la fonction malloc
• Rôle
– malloc permet d’allouer un bloc de mémoire – malloc permet d allouer un bloc de mémoire.
– La taille est passée en paramètres (en octets).
• Prototype
typedef unsigned int size_t;
void* malloc(size_t size);
• Fichier à inclure
#include <stdlib.h>
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 29
• Résultat
– malloc retourne l’adresse du bloc en cas de succès.
• Le bloc retourné N’EST PAS initialisé.
• La mémoire est réservée, pas de libération automatique.
– NULL en cas d’échec (le tas ne comporte pas un bloc suffisant).
Allocation – la fonction malloc - exemple int main()
{ {
void* bloc;
bloc = malloc(1000);
if (bloc != NULL)
printf("Succes\n");
else
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 30
printf("Echec\n");
system("PAUSE");
return 0;
}
Allocation dynamique de mémoire
Utilisation comme une variable int main()
{
double* bloc;
bloc = (double*)malloc(sizeof(double));
if (bloc != NULL) {
*bloc = 3.14;
printf("Succes: %lf\n", *bloc);
} } else
printf("Echec\n");
system("PAUSE");
return 0;
}
Utilisation comme un tableau de taille variable
double* generer_sinus(double amplitude, int nombre_points) {
double* valeurs;
int i;
valeurs = (double*)malloc(nombre_points * sizeof(double));
if (valeurs != NULL) {
for (i = 0; i < nombre_points; i++)
valeurs[i] = amplitude * sin(i * 2 * M_PI / nombre_points);
}
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 32
}
return valeurs;
}
Allocation dynamique de mémoire
Utilisation comme une structure de taille variable
typedef struct {
int taille;
int taille;
double valeurs[0];
} tableau_points;
tableau_points* generer_sinus(double amplitude, int nombre_points) {
tableau_points* tableau;
int i;
tableau = (tableau_points*)malloc(
sizeof(tableau_points) + nombre_points * sizeof(double));
if (tableau != NULL) {
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 33
{
tableau->taille = nombre_points;
for (i = 0; i < nombre_points; i++)
tableau->valeurs[i] = amplitude * sin(i * 2 * M_PI / nombre_points);
}
return tableau;
}
Utilisation comme une structure de taille variable – vue mémoire
int taille;
typedef struct {
int taille;
int taille;
double valeurs[0];
} tableau_points;
tableau = (tableau_points*)malloc(
sizeof(tableau_points) +
nombre points * sizeof(double)); double valeurs[];
Alignement mémoire
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 34
nombre_points * sizeof(double)); double valeurs[];
Allocation dynamique de mémoire
Libération avec free
• La taille du tas est limitée.
L ’ bl ll é ’ t l tili é
• Lorsqu’un bloc alloué n’est plus utilisé
– Il faut le restituer sur le tas.
– Il pourra ainsi être réutilisé pour un malloc ultérieur.
• La fonction free permet de libérer un bloc.
void free(void *memblock);
Libération avec free - Exemple int main()
{
void* bloc;
bloc = malloc(1000);
if (bloc != NULL) {
printf("Succes\n");
free(bloc);
}
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 36
} else
printf("Echec\n");
system("PAUSE");
return 0;
}
Allocation dynamique de mémoire
Les dangers - débordement lors de l’accès à un bloc - exemple double* generer_sinus(double amplitude, int nombre_points) {
{
double* valeurs;
int i;
valeurs = (double*)malloc(nombre_points * sizeof(double));
if (valeurs != NULL) {
for (i = 0; i <= nombre points; i++)
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 37
for (i 0; i < nombre_points; i++)
valeurs[i] = amplitude * sin(i * 2 * M_PI / nombre_points);
}
return valeurs;
}
Les dangers - débordement lors de l’accès à un bloc - conséquences
• Ecriture dans le tas hors de la zone réservée.
Ri d ti d d é
• Risque de corruption de données.
• Risque de corruption de la structure du tas.
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 38
Allocation dynamique de mémoire
Les dangers - Utilisation d’un bloc précédemment libéré
int main() {
do ble* bloc
Attention ! double* bloc;
bloc = (double*)malloc(sizeof(double));
if (bloc != NULL) {
*bloc = 3.14;
printf("Succes: %lf\n", *bloc);
free(bloc);
*bloc = 1.0;
}
Utilisation d’une zone mémoire qui n’est plus réservée !
Comportement indéfini.
} else
printf("Echec\n");
system("PAUSE");
return 0;
}
Les dangers - Libération d’un bloc non alloué int main()
{
double* bloc;
double x;
x = 1.2;
bloc = &x;
free(bloc);
system("PAUSE");
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 40
system("PAUSE");
return 0;
}
• Comportement indéfini.
Allocation dynamique de mémoire
Les dangers - Fuites de mémoire
• Si le programme ne libère pas la mémoire allouée
Son occ pation mémoire a gmente à chaq e no elle allocation – Son occupation mémoire augmente à chaque nouvelle allocation.
– Consommation progressive de toute la mémoire.
– Situation catastrophique :
• Impossibilité de fonctionner.
• Blocage de toutes les fonctions de l’ordinateur.
• Dans la pratique
– Programmes qui plantent au bout de quelques heures ou jours
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 41
Programmes qui plantent au bout de quelques heures ou jours.
– Pas de stabilité dans le temps.
Allocation dynamique de mémoire
Les dangers - Fuites de mémoire
• Exemple
int main() int main() {
int i;
for (;;)
malloc(100000);
system("PAUSE");
return 0;
}
Consommation rapide des 2 GB de mémoire disponible
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 42
Terminaison du programme, Retour à la normale.
Utilisation du fichier d’échange.
Ralentissement complet du PC.
de mémoire disponible
Allocation dynamique de mémoire
Autres fonctions - calloc
• Prototype
void * calloc (size t count size t size);
void * calloc (size_t count, size_t size);
• Effet
– Alloue count x sizeoctets
– Initialise toute la zone mémoire avec des zéros.
• Remarques
– Effet similaire à malloc, avec en plus initialisation de la mémoire.
é é ê é é
– La mémoire doit également être libérée avec free.
Autres fonctions - realloc
• Prototype
oid * realloc ( oid * ptr si e t si e) void * realloc (void * ptr, size_t size);
• Effet
– Réalloue un bloc de mémoire à une nouvelle taille.
– Si ptr est NULL, crée un nouveau bloc.
– Si la réallocation échoue, retourne NULL. Le bloc passé en paramètre reste alors inchangé.
– En cas de succès l’adresse retournée peut être différent de ptr
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 44
En cas de succès, l adresse retournée peut être différent de ptr.
Le bloc initialement pointé par ptr a alors été libéré.
– Le bloc réalloué est initialisé avec le contenu du bloc ptr.
L’espace supplémentaire est non initialisé.
Allocation dynamique de mémoire
alloca : allocation dynamique sur la pile
• Prototype
#include <malloc h>
#include <malloc.h>
void* alloca(size_t size);
• Effet
– Réserve un espace sur la pile.
• Exécution très rapide (pas de recherche d’un bloc vide).
• Pas de fragmentation de la mémoire.
– La taille est définie dynamiquement à l’exécution
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 45
La taille est définie dynamiquement à l exécution.
– L’espace est libéré à la sortie de la fonction appelante.
– NE PAS retourner l’adresse obtenue.
– NE PAS APPELER free.
alloca : allocation dynamique sur la pile
int main() {
do ble* tablea double* tableau;
int i, nombre_valeurs;
printf("Nombre de valeurs: ");
scanf("%d", &nombre_valeurs);
// allocation dynamique d'un tableau sur la pile
tableau = (double*)alloca(nombre_valeurs * sizeof(double));
for (i = 0; i < nombre_valeurs; i++) {
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 46
{
printf("Valeur n %d:", i + 1);
scanf("%lf", &tableau[i]);
}
system("PAUSE");
return 0;
// libération automatique de l’espace alloué par alloca }
Fonctions de manipulation de la mémoire
Introduction
• Besoin fréquent d’opérations sur la mémoire
Notamment a ec les tablea – Notamment avec les tableaux.
– Il existe très peu d’opérations sur la tableaux en langage C.
• Exemples d’opérations
– Initialisation d’un zone mémoire (ou d’un tableau).
– Copie.
– Déplacement.
Comparaison – Comparaison.
Exemple : initialisation de la mémoire
void initialiser(void * memoire, int taille, char valeur)
char valeur) {
int i;
for (i = 0; i < taille; i++)
((char*)memoire)[i] = valeur;
}
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 48
}
• Fonctions d’usage très courant
• Disponibles dans la bibliothèque standard.
– Implémentation optimisée.
Fonctions de manipulation de la mémoire
string.h
// Initialiser une zone mémoire void* memset(void * ptr, int value,
size_t num);_ // Copier une zone mémoire
void* memcpy(void * destination, const void * source, size_t num);
// Copier une zone mémoire.
// Fonctionne bien même en cas de recouvrement des 2 zones // mais plus lente que memcpy.
void* memmove(void * destination, const void * source,
i t )
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 49
size_t num);
// Comparer deux zones
int memcmp(const void * ptr1, const void * ptr2, size_t num);
// Recherche d'un caractère. Renvoie l’adresse de la 1ère occurrence.
void* memchr(const void * ptr, int value, size_t num);
Qu’avons-nous appris ?
• Les opérations sur les pointeurs L’ ll ti d i d é i
• L’allocation dynamique de mémoire
– Application au cas des tableaux de taille variable.
• Les fonctions de manipulation de la mémoire.
Analyse et programmation 2 - Les pointeurs et l'allocation dynamique de mémoire 50