• Aucun résultat trouvé

Les pointeurs et l’allocation dynamique de émémoire

N/A
N/A
Protected

Academic year: 2022

Partager "Les pointeurs et l’allocation dynamique de émémoire"

Copied!
27
0
0

Texte intégral

(1)

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

(2)

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.

(3)

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;

(4)

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

(5)

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

} }

(6)

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)

. . .

(7)

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 *

(8)

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

}

(9)

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

(10)

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.

(11)

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

}

(12)

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

}

(13)

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

(14)

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

(15)

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

(16)

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;

}

(17)

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;

}

(18)

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

(19)

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;

}

(20)

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;

}

(21)

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.

(22)

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.

(23)

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.

(24)

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.

(25)

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

(26)

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

Vos questions

(27)

Références

Documents relatifs

◮ Une fois cet espace créé, les paramètres actuels dans l’appel sont placés dans les cases mémoire réservées pour chaque paramètre. ◮ À la fin de l’exécution

a+i c’est l’adresse du i-ème élément du tableau a+i c’est aussi &amp;a[i]. L’incrément/décrément dépend du type de

•  Note: malloc et free peuvent être utilisés pour allouer un bloc mémoire une variable du type pointé (un tableau d’1 seul élément)... Erreur

Adapter la fonction de création pour créer une liste linéaire chaînée dans l'ordre FIFO à partir de ce fichier binaire.. Exercice 2 : Supposons que les données

Pour représenter une liste d'entiers sous forme chaînée, on crée le modèle de structure cellule qui a deux champs : un champ valeur de type int , et un champ suivant

- Le pointeur « ptr » contient l’adresse mémoire d’une zone mémoire capable de contenir une variable de type « int ».. - La définition d’un pointeur n’alloue en

Il est impé ératif d ratif d’ ’appeler l appeler l’ ’op opé érateur rateur delete delete lorsqu lorsqu’ ’on n on n’ ’a plus besoin a plus besoin de l de l’ ’espace

Allocation d’un bloc mémoire de 20 octets pour stocker 5 int. Ecriture de l’adresse de la 1ère case du bloc