Programmation impérative

Documents pareils
Programmation impérative

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Bases de programmation. Cours 5. Structurer les données

Conventions d écriture et outils de mise au point

Chapitre 1 : La gestion dynamique de la mémoire

PROJET ALGORITHMIQUE ET PROGRAMMATION II

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Le langage C. Séance n 4

Poker. A rendre pour le 25 avril

Les structures. Chapitre 3

Cours d initiation à la programmation en C++ Johann Cuenin

Travaux Dirigés n 1 : chaînes de caractères

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Algorithmique et Programmation, IMA

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Chap III : Les tableaux

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Programmation C++ (débutant)/instructions for, while et do...while

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

Les chaînes de caractères

I. Introduction aux fonctions : les fonctions standards

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Analyse de sécurité de logiciels système par typage statique

Suivant les langages de programmation, modules plus avancés : modules imbriqués modules paramétrés par des modules (foncteurs)

Les arbres binaires de recherche


Projet d informatique M1BI : Compression et décompression de texte. 1 Généralités sur la compression/décompression de texte

Les structures de données. Rajae El Ouazzani

Cours de Programmation Impérative: Zones de mémoires et pointeurs

UE C avancé cours 1: introduction et révisions

Le prototype de la fonction main()

GESTION DES FICHIERS C/UNIX

Compression de Données - Algorithme de Huffman Document de Conception

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Introduction à la Programmation Parallèle: MPI

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

Traduction des Langages : Le Compilateur Micro Java

Initiation. àl algorithmique et à la programmation. en C

Java Licence Professionnelle CISII,

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Cours 1: Java et les objets

Dans le chapitre 1, nous associions aux fichiers ouverts des descripteurs de fichiers par lesquels nous accédions aux fichiers.

Programmation C. Apprendre à développer des programmes simples dans le langage C

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

TP : Gestion d une image au format PGM

Arguments d un programme

TP3 : Manipulation et implantation de systèmes de fichiers 1

Utilisation d objets : String et ArrayList

as Architecture des Systèmes d Information

Plan du cours. Historique du langage Nouveautés de Java 7

Cours Programmation Système

Algorithmique, Structures de données et langage C

Les fichiers. Chapitre 4

SUPPORT DE COURS. Langage C

Cahier des charges. driver WIFI pour chipset Ralink RT2571W. sur hardware ARM7

Programmation en langage C

C++ Programmer. en langage. 8 e édition. Avec une intro aux design patterns et une annexe sur la norme C++11. Claude Delannoy

Structure fonctionnelle d un SGBD

Introduction à la programmation Travaux pratiques: séance d introduction INFO0201-1

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

OS Réseaux et Programmation Système - C5

Cours de Systèmes d Exploitation

et Programmation Objet

Le système de gestion des fichiers, les entrées/sorties.

Programmation système I Les entrées/sorties

Premiers Pas en Programmation Objet : les Classes et les Objets

INITIATION A LA PROGRAMMATION

Seance 2: En respectant la méthode de programmation par contrat, implémentez les autres fonctions de jeu.

C++ COURS N 2 : CLASSES, DONNÉES ET FONCTIONS MEMBRES Classes et objets en C++ Membres d'une classe Spécification d'une classe Codage du comportement

NIMEGUE V3. Fiche technique 3.07 : Sauvegarde / Restauration manuelle

Projet de Veille Technologique

#include <stdio.h> #include <stdlib.h> struct cell { int clef; struct cell *suiv; };

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

TD3: tableaux avancées, première classe et chaînes

Architecture des ordinateurs

Claude Delannoy. 3 e édition C++

Cours 1 : Qu est-ce que la programmation?

Quelques algorithmes simples dont l analyse n est pas si simple

Table des matières. Chapitre 4 : Variables pointeurs

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Cours d Algorithmique et de Langage C v 3.0

Introduction au langage C

STAGE IREM 0- Premiers pas en Python

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Vous avez cliqué sur le lien disponible sur le Site Uniformation. Vous venez d arriver sur cette page.

INF111. Initiation à la programmation impérative en C amini/cours/l1/inf111/ Massih-Reza Amini

RACCOURCIS CLAVIERS. DEFINITION : Une «combinaison de touches» est un appui simultané sur plusieurs touches.

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

L exclusion mutuelle distribuée

Langage Java. Classe de première SI

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Pensez à vous inscrire... si ce n est pas encore fait

Présentation du PL/SQL

ARDUINO DOSSIER RESSOURCE POUR LA CLASSE

TP, première séquence d exercices.

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

Transcription:

Programmation impérative Cours 3 : Allocation de mémoire en C Catalin Dima

Utilisation des pointeurs Pointeur pointant sur une adresse déjà en utilisation par une autre variable (individuelle, tableau, etc.) Astucieux, mais est-ce tellement utile?... Pointeur pointant sur une zone de mémoire nouvellement réservée. Idée : on ne connaît pas à l avance (c.à.d. à la compilation!) si on aura besoin de zones supplémentaires de zone pour stocker des valeurs calculées. Exemple : tableau de taille variable. Exemple 2 : liste de valeurs dans laquelle on insère ou on supprime au gré de l utilisation du programme. Exemple 3 : matrices creuses. Exemple 4,5,6,7,8... : arbres/hastables/diverses structures de données.

Allocation de mémoire : malloc Supposons qu on veut écrire un programme qui manipule des séquences de valeurs entières saisies par l utilisateurs, suite de taille variable, donnée par l utilisateur et qui peut être différente entre deux saisies différentes. 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 veut saisir. Mais à chaque exécution il y aura 2000-taille cases mémoire inutilisées! Et, en plus, il faut contraindre l utilisateur à saisir une valeur taille <= 2000! Il ne sera pas content s il doit travailler avec 3000 valeurs!

Allocation de mémoire : malloc Supposons qu on veut écrire un programme qui manipule des séquences de valeurs entières saisies par l utilisateurs, suite de taille variable, donnée par l utilisateur et qui peut être différente entre deux saisies différentes. 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 veut saisir. Mais à chaque exécution il y aura 2000-taille cases mémoire inutilisées! Et, en plus, il faut contraindre l utilisateur à saisir une valeur taille <= 2000! Il ne sera pas content s il doit travailler avec 3000 valeurs! Solution : malloc fonction qui réserve une zone de mémoire (contiguë) de taille donnée en paramètre et renvoie sa première adresse en résultat, de sorte à ce qu on puisse l affecter à un pointeur : ptr = malloc(3000); On dit qu on alloué 3000 octets au pointeur ptr.

Utilisation de malloc Déclaration void *malloc(size_t dimension) : size_t : dimension de la zone de mémoire à réserver, en octets. void * : par défaut, malloc renvoie un pointeur sans type, c est à nous d utiliser l espace réservé avec un type particulier... par exemple en l affectant à un pointeur char : char * ptr; ptr = (char*) malloc(3000); Bibliothèque qui contient la fonction malloc : stdlib.h (à inclure avec #include!).

Exemple Pour notre exemple de réservation d une zone de mémoire pour un tableau d entiers : int * tbl, taille; scanf("%d",&taille); tbl = (int *)malloc(taille * sizeof(int)); Fonction sizeof (opérateur!) nous donne la taille d un type de données (ici int) elle peut varier d un compilateur à l autre! Résultat (pour un compilateur pour lequel un int est codé sur 4 octets) : réservation de 12000 octets, dont la première adresse est pointée par ptr. Les 12000 octets pourront être utilisés comme un tableau de 3000 entiers. Donc ptr[4] =4567 stocke la valeur 4567 sur les 4 octets qui se trouvent à l adresse ptr + 16(octets). (dessin au tableau) Attention! Ne pas "perdre" l adresse de la zone allouée avec malloc, car elle ne peut plus être retrouvée! Donc si vous jouez avec la valeur de tbl, faites en sorte que vous pouviez faire le calcul inverse et revenir à la valeur que malloc vous a envoyée juste après le scanf ci-dessus. Un autre appel à malloc ne vous enverra pas l adresse antérieure que vous avez perdue!

calloc Une allocation mémoire (un peu) plus structurée se fait avec void *calloc(size_t nbre, size_t tailledunecase), équivalente à malloc(nbre * tailledunecase) : int *tbl, taille; scanf("%d",&taille); tbl = (int *)calloc(taille, sizeof(int)); Une petite différence : calloc initialise à 0 toutes les cases allouées.... à la différence de malloc qui fournit les cases mémoire telles quelles (avec les éventuels restes des calculs précédents).... ce qui peut être embêtant si on oublie d instancier les cases d un tableau, en considérant qu avant toute utilisation elles ont la valeur 0.

realloc : changer d avis Si jamais on se rend compte que la zone de mémoire allouée est trop petite ou trop grande, il faut allouer une zone de taille différente. On peut bien-sûr le faire à l aide de malloc/calloc, mais...... il faut pas oublier de copier dedans toutes les valeurs qu on avait stockées dans la première zone! realloc fait ce boulot pour nous : void *realloc(void *ptrancien, size_t nvlletaille) : on donne le pointeur ancien (qui identifie la zone de mémoire utilisée jusqu alors), et la nouvelle taille qu on veut voir allouer au pointeur ancien. Effet de l instruction ptr = realloc(ptr, nvlletaille) : Une nouvelle zone de mémoire est réservée. Le contenu de la zone de mémoire allouée à ptr est copié (octet par octet), au début de cette nouvelle zone. Le résultat retourné est un pointeur qui pointe sur le premier octet de cette nouvelle zone de mémoire. L ancienne zone est déclarée inutilisée. Si la taille de la nouvelle zone est plus grande que celle de l ancienne zone, tout le contenu de l ancienne est copié. Si la taille est plus petite, on recopie que ce qui rentre dans la nouvelle zone, à partir du premier octet. Si, pour une raison ou une autre, on ne peut pas réallouer la mémoire, la valeur renvoyée sera NULL (ou 0 sur 4 octets) et l ancienne zone ne sera pas déclarée libérée. Donc faire bien attention! ne jamais faire ptr = realloc(ptr,nvval), car on risque de se retrouver avec un pointeur null et de perdre la référence de l ancienne zone de mémoire, et tout son contenu!

free : prendre soin de ne pas avoir de fuites de mémoire Lorsqu une zone de mémoire allouée cesse d être nécessaire, que fait-on avec? Il faut la marquer comme étant disponible pour des allocations ultérieures! void free(void *ptr) fait le boulot : prend un pointeur en paramètre et, en considérant que sa valeur représente une zone de mémoire allouée, la marque comme étant désalouée et, donc, utilisable par un malloc/calloc/realloc ultérieur. Si ptr ne pointe pas sur une zone précédemment allouée (avec un malloc ou compagnie), le comportement peut devenir bizarre...! Si ptr est NULL (c.à.d. 0), il ne se passe rien. Donc, pour éviter des problèmes, la suggestion est d enchaîner un free avec une affectation de valeur NULL : int *ptr; ptr = (int *) malloc(sizeof(int));... free(ptr); ptr = NULL;

Listes chaînées Les tableaux sont utiles pour le stockage simultané des valeurs d un type donné. Mais parfois on est amené à prévoir le rajout, une par une, d une suite de valeurs du même type. Liste chaînées : suite de cellules, chacune composée d une valeur et d un pointeur indiquant la place de la prochaine cellule dans la suite : @100 10 345 @345 20 829 @829 30 116 @116 40 266 @266 50 NULL La position des cellules en mémoire peut ne pas correspondre à leur place dans la suite!

Déclaration de listes chaînées Supposons que la valeur à stocker est un entier sur 4 octets : struct liste{ int val; struct liste *ptr; }; struct liste *x; En tant que pointeur, x contient une adresse, et *x est la donnée stockée à cette adresse. En tant que struct, *x possède deux champs : (*x).val et (*x).ptr. Raccourci de notation : x->val, respectivement x->ptr. x->val est la valeur stockée dans la cellule pointée par la variable x. x->ptr est le pointeur stocké dans la cellule pointée par la variable x. À noter que x->ptr est lui-même un pointeur! x->ptr->val est la valeur stockée dans la cellule pointée par la variable x->ptr. x->ptr->ptr est le pointeur stocké dans la cellule pointée par la variable x->ptr.

Exemple de liste chaînée @100 10 345 @345 20 829 @829 30 116 @116 40 266 @266 50 NULL Supposons que la variable x, déclarée en tant que struct liste *x, stocke la valeur (adresse!) @100. Combien vaut x->val? Combien vaut x->ptr? Combien vaut x->ptr->val? Combien vaut x->ptr->ptr->ptr? Combien vaut x->ptr->ptr->ptr->ptr->ptr->ptr?

Exemple, suite Combien vaut x->val? 10 Combien vaut x->ptr? @345 Combien vaut x->ptr->val? 20 Combien vaut x->ptr->ptr->ptr? @116 Combien vaut x->ptr->ptr->ptr->ptr->ptr->ptr? Erreur sémantique! (l exécution d une instruction contenant cette expression peut crasher le programme!)

Exemple, création d une liste chaînée Une liste chaînée est créée à l aide de malloc/calloc! Mais combien doit-on réserver pour une cellule de type struct liste? Rien de plus simple! sizeof(struct liste) nous renvoie la bonne réponse! struct liste *cell; // on peut réutiliser la déclaration du type liste! cell = (struct liste*) malloc(sizeof(struct liste)); cell->val = 10; cell->ptr=null;

Création d une liste chaînée, 1er essai Et maintenant créons une liste contenant 3 valeurs lues à l entrée std : struct liste *cell1, *cell2, *cell3; cell1 = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell1->val); // eh oui! cell1->val n est pas un pointeur! cell2 = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell2->val); cell3 = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell3->val); // et il faut connecter les 3 cellules! cell1->ptr = cell2; cell2->ptr = cell3; cell3->ptr = NULL;

Création algorithmique d une liste chaînée Mouais, mais c est pas joli! On veut le faire pour n importe quel nombre de cellules! Il faut faire une boucle!

Création algorithmique d une liste chaînée Créer la première cellule d abord, puis les autres en allouant le pointeur dans chaque cellule : struct liste *cell; int i; cell = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell->val); for (i=0,i<2;i++){ cell->ptr = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell->ptr->val); // c est là qu il faut mettre la valeur! cell->ptr->ptr = NULL; // le champ pointeur de la nouvelle cellule! cell = cell->ptr ; // on passe au suivant! } Mais... gros problème! Comment on revient à la tête de liste?... ben, on l a perdue!!

Création algorithmique d une liste chaînée (2) struct liste *cell, *tete; int i; cell = (struct liste*) malloc(sizeof(struct liste)); tete = cell; // et maintenant on la perd plus! scanf("%d",&cell->val); for (i=0,i<2;i++){ cell->ptr = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell->ptr->val); // c est là qu il faut mettre la valeur! cell->ptr->ptr = NULL; cell = cell->ptr ; // on passe au suivant! }

Création algorithmique d une liste chaînée (3) On peut aussi créer cette liste dans l ordre inverse : struct liste *cell, *cellprec; int i; cellprec = NULL; for (i=0,i<3;i++){ cell = (struct liste*) malloc(sizeof(struct liste)); scanf("%d",&cell->val); cell->ptr = cellprec; cellprec = cell; // et la prochaine fois on insère en tête de liste! }

Fonctionnement de malloc/calloc/realloc/free La mémoire du programme est découpée en plusieurs parties : Zone de code (text). Zone des données initialisées (variables déclarées globales). Tas = zone d allocation dynamique de mémoire. Pile - zone d allocation de mémoire pour les paramètres et les variables déclarées dans les fonctions, et pour la valeur de retour. Tout malloc va chercher dans le tas une zone de mémoire de taille suffissante pour l allouer. Les zones allouées sont marquées dans des octets spéciaux (qui sont réservés en supplément des octets demandés). Les zones libres sont mises elles aussi dans une liste chaînée. Chaque allocation diminue une zone libre, ou la supprime carrément de la liste des zones libres, et remplit les octets d information de la zone réservée. Chaque free fait le contraire, en fusionnant éventuellement des zones libres si elles deviennent contiguës. Différentes implémentations de ces principes existent celle sous Linux est la bibliothèque glibc.