• Aucun résultat trouvé

Si nous n'avons plus besoin d'un bloc de mémoire que nous avons réservé à l'aide de malloc, alors nous pouvons le libérer à l'aide de la fonction free de la bibliothèque <stdlib>.

free( <Pointeur> )

libère le bloc de mémoire désigné par le <Pointeur>; n'a pas d'effet si le pointeur a la valeur zéro.

Attention !

* La fonction free peut aboutir à un désastre si on essaie de libérer de la mémoire qui n'a pas été correctement allouée par malloc.

* La fonction free ne change pas le contenu du pointeur; il est conseillé d'affecter la valeur NULL au pointeur immédiatement après avoir libéré le bloc de mémoire qui y était attaché.

* Si nous ne libérons pas explicitement la mémoire à l'aide free, alors elle est libérée automatiquement à la fin du programme.

E

XERCICES ENCOURS

Ecrire un programme qui lit 10 mots au clavier (longueur maximale: 50 caractères) et attribue leurs adresses à un tableau de pointeurs MOT. Effacer les 10 mots un à un, en suivant l'ordre

lexicographique et en libérant leur espace en mémoire. Afficher à chaque fois les mots restants en attendant la confirmation de l'utilisateur (par 'Enter').

Ecrire un programme qui lit 10 mots au clavier (longueur maximale: 50 caractères) et attribue leurs adresses à un tableau de pointeurs MOT. Copier les mots selon l'ordre lexicographique en une seule 'phrase' dont l'adresse est affectée à un pointeur PHRASE. Réserver l'espace nécessaire à la PHRASE avant de copier les mots. Libérer la mémoire occupée par chaque mot après l'avoir copié. Utiliser les fonctions de <string>.

Ecrire un programme qui lit 10 phrases au clavier (longueur maximale: 50 caractères) et attribue leurs adresses à un tableau de pointeurs MOT. Réserver dynamiquement l'emplacement en mémoire pour les mots. Trier les phrases lexicographiquement en n'échangeant que les pointeurs. Utiliser la méthode de tri par propagation (méthode de la bulle - décrite dans l'exercice 7.15).

14

C

HAPITRE

14 -L

ES SOUS

-

PROGRAMMES EN LANGAGE

C

14.1 Modularité du code

Un programme bien écrit doit être structuré et décomposé en sous-programmes (ou module), chacun associé à une tache précise.

Bien qu’en C tout soit fonction, on distingue en général deux types de sous-programme : Les

procédures et les fonctions. Les procédures communiquent avec les autres sous-programmes via

leur zone de paramètres (ou arguments) que l’on appellera le tube. Les fonctions disposent également du mécanisme de tube, mais profite, en plus, d’un mécanisme de retour leur permettant de retourner une et une seule valeur de type scalaire au sous-programme qui a fait appel à elles (qu’on appelle « l’appelant »).

Nous venons de le dire, le langage C ne fait pas la distinction entre les procédures et les fonctions. Pour ce langage, tout est considéré comme une fonction. Une procédure sera alors vue comme une fonction qui fait son traitement mais ne retourne rien. La non-utilisation du mécanisme de retour se traduira par le mot clef void placé avant le nom du sous-programme.

Le programme principal est une fonction particulière (le plus souvent de type int, d’où le return 0) qui doit obligatoirement figurer dans tout programme car il en constitue le point d’entrée appelé par le

système d’exploitation.

Pour qu’un sous-programme soit actif (c'est-à-dire qu’il prenne le contrôle du processeur), il doit être appelé par un autre sous-programme. On distinguera alors le sous-programme appelé et le sous- programme appelant. L’appelant enregistre l’adresse de sa prochaine instruction à exécuter dans une pile d’adresse spécifique puis libère le processeur au profit de l’appelé. Après exécution, l’appelé rend le processeur à l’appelant qui dépile son adresse de retour (ou de reprise) et continue alors son exécution là où il s’était arrêté.

14.2 Visibilité des sous-programmes

Le compilateur n’autorise l’appel d’un sous-programme que s’il en connaît déjà l’existence ainsi que le nombre et le type des paramètres et de la valeur de retour dans le cas d’une fonction.

void paf() { } void pif() { paf() ; } void main() { pif() ; paf() ; }

Le programme principal « voit » les 2 sous-programmes, pif « voit » paf, mais paf ne voit pas pif.

Problème : lorsque le sous-programme n’a pas été défini dans le même fichier que le programme

appelant ni dans un fichier « .h » que l’on peut inclure.

14.2.1 Prototype d’un sous-programme

Le prototype d’un sous-programme contient les informations suivantes : o le type de valeur retournée dans le cas d’une fonction

o le nom du sous-programme

o la liste des paramètres du sous-programme sous forme : type [+ nom] (optionnel)

Exemple : pour la fonction int minimum (int A, int B) {

… }

Le prototype est int minimum(int,int) ;

Ou encore int minimum(int A, int B) ; // à éviter car les noms de variables sont // inutiles dans les prototypes

Comme toute déclaration, le prototype est suivi d’un point virgule.

Le prototype permet au compilateur de vérifier la validité des appels ultérieurs au sous-programme dans le programme ; lorsque le sous-programme n’a pas été écrit dans le même fichier ou lors d’appels croisés entre deux sous-programmes.

En règle générale, les prototypes de fonctions et de procédures sont écrits dans un fichier « .h » qui sera inclus dans les fichiers manipulant les sous-programmes.

14.2.2 Déclaration en fichier bibliothèque .h

Les fichiers de bibliothèque d’extension .h sont destinés à contenir des lignes de code à inclure dans un autre fichier source au moment de la compilation.

L’instruction d’inclusion sera par exemple : #include c :\tmp\mabib.h  Remarque :

Notez la différence avec les bibliothèques de fonctions prédéfinies offertes par le langage que vous allez inclure en écrivant : #include <stdio.h>

Mettre dans ces fichiers les prototypes de vos fonctions ainsi que la déclaration de vos constantes permet de les rendre accessibles depuis tous les programmes C qui auront inclus la bibliothèque. Exactement comme vous faisiez pour profiter des fonctions prédéfinies du langage.

Documents relatifs