• Aucun résultat trouvé

Langage C Allocation dynamique de mémoire

N/A
N/A
Protected

Academic year: 2022

Partager "Langage C Allocation dynamique de mémoire"

Copied!
23
0
0

Texte intégral

(1)

Langage C

Allocation dynamique de mémoire

(2)

Pointeur : variable qui peut stocker l’adresse d’une autre variable

Variable j

(stocke la valeur)

Pointeur p_j

(stocke l’adresse)

&j

*p_j

Permet de manipuler des variables par leur adresse (unique dans la mémoire)

Passage d’arguments par adresse

void Mafonction(int* p1, int* p2, ... );

=> Nombre illimité d’arguments de sortie

Tableau = pointeur + bloc mémoire

tab[4] *(tab + 4)

&tab[2] tab + 2

(3)

int tab[5];

Allocation statique de mémoire

4 octets

0xD080 0xD084

. . .

. . . . . .

tab 0xD080

tab[0] tab[1]

1. Définition d’un pointeur tab

2. Allocation d’un bloc mémoire de 5 x4octets contigües

tab contient l’adresse du 1er élément du tableau

(4)

int tab[5];

4 octets

0xD080 0xD084

. . .

. . . . . .

tab 0xD080

tab[0] tab[1]

Il faut connaître la taille du tableau à la compilation

Problématique dans beaucoup de cas

(ex. Ouvrir une image PGM de taille inconnue…) int dim ;

scanf(“%d”,&dim);

int tab[dim];

Ca ne marche pas

Rappel:

(5)

Allocation statique de mémoire

4 octets

0xD080 0xD084

. . .

. . . . . .

tab 0xD080

tab[0] tab[1]

Il faut connaître la taille du tableau à la compilation

Problématique dans beaucoup de cas

(ex. Ouvrir une image PGM de taille inconnue…)

Un tableau

=

un pointeur +

un bloc mémoire

On pourrait déclarer le pointeur (int* tab;)

Puis allouer le bloc mémoire

quand on en a besoin

(6)

On ne connaît pas la taille à la compilation

int dim;

int* tab;

scanf(“%d”,&dim);

tab = malloc (dim*sizeof(int));

free(tab);

. . .

. . . . . .

tab

Allocation d’un espace mémoire pour stocker l’adresse d’un int

On ne connaît

pas sa taille

(7)

Allocation dynamique de mémoire

On ne connait pas la taille à la compilation

int dim;

int* tab;

scanf(“%d”,&dim);

tab = malloc (dim*sizeof(int));

free(tab);

. . .

. . . . . .

tab

dim = 5;

On connait la

taille de tab

(8)

On ne connait pas la taille à la compilation

int dim;

int* tab;

scanf(“%d”,&dim);

tab = malloc (dim*sizeof(int));

free(tab);

4 octets

0xD080 0xD084

. . .

. . . . . .

tab 0xD080

tab[0] tab[1]

Nombre d’octets

à allouer 1. Allocation d’un bloc mémoire de 20 octets pour stocker 5 int

2. Ecriture de l’adresse de la 1ère case du bloc dans tab

dans

<stdlib.h>

(9)

Allocation dynamique de mémoire

On ne connait pas la taille à la compilation

int dim;

int* tab;

scanf(“%d”,&dim);

tab = malloc (dim*sizeof(int));

free(tab);

. . . . . .

tab

Libération de la mémoire allouée pour tab

. . .

0xD080 0xD084

(10)

Si l’allocation échoue, malloc renvoie le pointeur NULL (adresse #0000 qui ne correspond en fait à aucune zone de mémoire accessible)

Bonne pratique : libérer la mémoire allouée avec free(tab); (Essentiel lorsqu’on manipule de grands tableaux ou qu’on a peu de mémoire)

Un int peut occuper 2 ou 4 octets selon les machines sizeof( ) améliore la portabilité des programmes

Nombre d’octets

char 1

int 2 ou 4

double 8

tab = malloc(dim*sizeof(double));

if ( tab != NULL) { ... }

else printf(“Allocation impossible\n”);

(11)

Allocation dynamique dans les fonctions

Mauvaise méthode

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

Mafonction(tab, dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

}

. . .

. . . . . .

tab

. . . . . .

Allocation d’un espace mémoire pour stocker

l’adresse d’un int

(12)

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

Mafonction(tab, dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

}

Mauvaise méthode

. . .

. . . . . .

tab

. . . . . .

1. Création d’un pointeur T (variable locale) 2. Copie du contenu de tab dans T (mais il n’y a

rien dans tab…)

T

(13)

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

Mafonction(tab, dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

}

Allocation dynamique dans les fonctions

Mauvaise méthode

. . .

. . . . . .

tab

. . . . . .

0xD080 0xD084

T 0xD080

1. Allocation d’un bloc mémoire de 20 octets pour stocker 5 int

2. Ecriture de l’adresse de la 1ère case du bloc dans T

(14)

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

Mafonction(tab, dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

}

Mauvaise méthode

0000

0000 0000 0000

0000 0000 0000 0000 . . .

. . . . . .

tab

. . . . . .

0xD080 0xD084

T 0xD080

Lecture de l’adresse stockée dans T (0xD080) et écriture des 0 à partir de cette adresse

T[0] T[1]

(15)

Allocation dynamique dans les fonctions

Mauvaise méthode

0000

0000 0000 0000

0000 0000 0000 0000 . . .

. . . . . .

tab

1. T (variable locale) est détruit à la fin de la fonction 2. tab ne contient aucune adresse

0xD080 0xD084

?

tab[0] Plantage à l'exécution

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

Mafonction(tab, dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

}

(16)

int* Mafonction(int dim);

void main(){

int* tab;

dim = 5;

tab = Mafonction(dim);

printf(“%d”,tab[0]);

}

int* Mafonction(int dim){

int i; int* T;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

return T;}

Bonne méthode 1

0000

0000 0000 0000

0000 0000 0000 0000 . . .

. . . . . .

tab

. . . . . .

T

0xD080 0xD084

0xD080

Solution : Passer T en argument de sortie

0xD080

Copie de l’adresse contenue dans T (0xD080) dans tab

(17)

int* Mafonction(int dim);

void main(){

int* tab;

dim = 5;

tab = Mafonction(dim);

printf(“%d”,tab[0]);

}

int* Mafonction(int dim){

int i; int* T;

T=malloc(dim*sizeof(int));

for (i=0;i<dim;i++) T[i]=0;

return T;}

Allocation dynamique dans les fonctions

Bonne méthode 1

0000

0000 0000 0000

0000 0000 0000 0000 . . .

. . . . . .

tab

0xD080 0xD084

0xD080

tab[0] = 0

printf(“%d”,tab[0]) affiche 0

(18)

Bonne méthode 2 (malloc dans le main)

. . .

. . . . . .

tab

. . . . . .

0xD080 0xD084

0xD080

1. Allocation d’un bloc mémoire de 20 octets pour stocker 5 int

2. Ecriture de l’adresse de la 1ère case du bloc dans tab void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

tab=malloc(dim*sizeof(int));

Mafonction(tab,dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

for (i=0;i<dim;i++) T[i]=0;

}

(19)

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

tab=malloc(dim*sizeof(int));

Mafonction(tab,dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

for (i=0;i<dim;i++) T[i]=0;

}

Allocation dynamique dans les fonctions

Bonne méthode 2 (malloc dans le main)

. . .

. . . . . .

tab

. . . . . .

0xD080 0xD084

Création d’un pointeur T (variable locale) et écriture de l’adresse stockée dans tab

0xD080 T

0xD080

(20)

Bonne méthode 2 (malloc dans le main)

0000

0000 0000 0000

0000 0000 0000 0000 . . .

. . . . . .

tab

. . . . . .

0xD080 0xD084

T[0] T[1]

Lecture de l’adresse stockée dans T (0xD080) et écriture des 0 à partir de cette adresse

0xD080

T 0xD080

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

tab=malloc(dim*sizeof(int));

Mafonction(tab,dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

for (i=0;i<dim;i++) T[i]=0;

}

(21)

Allocation dynamique dans les fonctions

Bonne méthode 2 (malloc dans le main)

0000

0000 0000 0000

0000 0000 0000 0000 . . .

. . . . . .

tab

0xD080 0xD084

tab[0] tab[1]

1. T n’existe plus (variable locale)

2. Lecture de la valeur stockée à l’adresse tab

0xD080

tab[0] = 0

void Mafonction(int* T, int dim);

void main(){

int* tab;

dim = 5;

tab=malloc(dim*sizeof(int));

Mafonction(tab,dim);

printf(“%d”,tab[0]);

}

void Mafonction(int* T, int dim){

int i;

for (i=0;i<dim;i++) T[i]=0;

}

(22)

à la compilation

Si l’allocation échoue, tab = NULL

free(tab); libère la mémoire allouée pour tab

Tableau = pointeur + bloc mémoire

int* tab; tab = malloc (dim*sizeof(int));

Nombre d’octets à allouer Nombre de cases du

tableau Nombre d’octets

par case

(23)

Allocation dynamique : plus besoin de connaître la taille d’un tableau à la compilation

Allocation dans les fonctions:

Soit tab = malloc(...) dans la fonction et return tab;

Soit tab = malloc(...) dans le main() et tab en argument d’entrée de la fonction

Equivalence des notations:

void Mafonction(int* tab, ...)

void Mafonction(int *tab, ...)

void Mafonction(int tab[], …)

Références

Documents relatifs

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

qui nous met personnellement en jeu. Les données matérielles de l'expérience appellent toujours ce même coefficient d'intégration qui définit à la fois la

Dénition dans chromosome.c et test de la fonction mute sur un objet chromosome.. (int* mute(int*

- 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

◮ On peut le faire avec un tableau int tab[2000] et une variable supplémentaire int taille qui sera initialisée à chaque saisie avec le nombre de valeurs que l’utilisateur

Écrire un programme qui lit une suite d’entiers saisie au clavier et crée une liste chaînée (dans l’ordre de saisie), puis lit encode deux entiers n et pos et insère n à la

Les autres lignes d’adresse et les signaux de contrôle sont distribués identiquement sur tous les boîtiers...

Pour libérer de la mémoire allouée dynamiquement en C++, on utilisera l’opérateur delete...