Formation programmez en C++ et développez vos applications

Réflexions pédagogiques autour des enseignements en baccalauréat professionnel ELEEC

Manipulation de chaînes de caractères dans les macros

Le préprocesseur permet d’effectuer des opérations sur les chaînes de caractères. Tout argument de macro peut être transformé en chaîne de caractères dans la définition de la macro s’il est précédé du signe #. Par exemple, la macro suivante :
#define CHAINE(s) #s
transforme son argument en chaîne de caractères. Par exemple :
CHAINE(2+3)
devient :
« 2+3″
Lors de la transformation de l’argument, toute occurrence des caractères  » et \ est transformée respectivement en \ » et \\ pour conserver ces caractères dans la chaîne de caractères de remplacement.
Le préprocesseur permet également la concaténation de texte grâce à l’opérateur ##. Les arguments de la macro qui sont séparés par cet opérateur sont concaténés (sans être transformés en chaînes de caractères cependant). Par exemple, la macro suivante :
#define NOMBRE(chiffre1,chiffre2) chiffre1##chiffre2
permet de construire un nombre à deux chiffres :
NOMBRE(2,3)
est remplacé par le nombre décimal 23. Le résultat de la concaténation est ensuite analysé pour d’éventuels remplacements additionnels par le préprocesseur.

Les trigraphes

Le jeu de caractères utilisé par le langage C++ comprend toutes les lettres en majuscules et en minuscules, tous les chiffres et les caractères suivants :
. , ; : ! ?  » ‘ + – ^ * % = & | ~ _ # / \ { } [ ] () < >
Malheureusement, certains environnements sont incapables de gérer quelques-uns de ces caractères. C’est pour résoudre ce problème que les trigraphes ont été créés.
Les trigraphes sont des séquences de trois caractères commençant par deux points d’interrogations. Ils permettent de remplacer les caractères qui ne sont pas accessibles sur tous les environnements. Vous n’utiliserez donc sans doute jamais les trigraphes, à moins d’y être forcé. Les trigraphes disponibles sont définis ci-dessous :
Tableau 5-1. Trigraphes
Trigraphe Caractère de remplacement
??= #
??/ \
??’ ^
??( ^
??) [
??! ]
?? |
{ }
??- ~
6. Modularité des programmes et génération des binaires
6.1. Pourquoi faire une programmation modulaire ?
6.2. Les différentes phases du processus de génération des exécutables
6.3. Compilation séparée en C/C++
6.4. Syntaxe des outils de compilation
6.4.1. Syntaxe des compilateurs
6.4.2. Syntaxe de make
6.5. Problèmes syntaxiques relatifs à la compilation séparée
6.5.1. Déclaration des types
6.5.2. Déclaration des variables
6.5.3. Déclaration des fonctions
6.5.4. Directives d’édition de liens

Modularité des programmes et génération des binaires

La modularité est le fait, pour un programme, d’être écrit en plusieurs morceaux relativement indépendants les uns des autres. La modularité a d’énormes avantages lors du développement d’un programme. Cependant, elle implique un processus de génération de l’exécutable assez complexe. Dans ce chapitre, nous allons voir l’intérêt de la modularité, les différentes étapes qui permettent la génération de l’exécutable et l’influence de ces étapes sur la syntaxe du langage.

Pourquoi faire une programmation modulaire ?

Ce qui coûte le plus cher en informatique, c’est le développement de logiciel, pas le matériel. En effet, développer un logiciel demande du temps, de la main d’œuvre qualifiée, et n’est pas facile (il y a toujours des erreurs). De plus, les logiciels développés sont souvent spécifiques à un type de problème donné. Pour chaque problème, il faut tout refaire. Ce n’est pas un très bon bilan. Pour éviter tous ces inconvénients, une branche de l’informatique a été développée : le génie logiciel. Le génie logiciel donne les grands principes à appliquer lors de la réalisation d’un programme, de la conception à la distribution, et sur toute la durée de vie du projet. Ce sujet dépasse largement le cadre de ce cours, aussi je ne parlerais que de l’aspect codage seul, c’est-à-dire ce qui concerne le C/C++.Au niveau du codage, le plus important est la programmation modulaire.
Les idées qui en sont à la base sont les suivantes :
• diviser le travail en plusieurs équipes ;
• créer des morceaux de programme indépendants de la problématique globale, donc réutilisables pour d’autres logiciels ;
• supprimer les risques d’erreurs qu’on avait en reprogrammant ces morceaux à chaque fois.
Je tiens à préciser que les principes de la programmation modulaire ne s’appliquent pas qu’aux programmes développés par des équipes de programmeurs. Ils s’appliquent aussi aux programmeurs individuels. En effet il est plus facile de décomposer un problème en ses éléments, forcément plus simples, que de le traiter dans sa totalité (dixit Descartes).
Pour parvenir à ce but, il est indispensable de pouvoir découper un programme en sous-programmes indépendants, ou presque indépendants. Pour que chacun puisse travailler sur sa partie de programme, il faut que ces morceaux de programme soient dans des fichiers séparés. Pour pouvoir vérifier ces morceaux de programme, il faut que les compilateurs puissent les compiler indépendamment, sans avoir les autres fichiers du programme. Ainsi, le développement de chaque fichier peut se faire relativement indépendamment de celui des autres. Cependant, cette division du travail implique des opérations assez complexes pour générer l’exécutable.

Les différentes phases du processus de génération des exécutables

Les phases du processus qui conduisent à l’exécutable à partir des fichiers sources d’un programme sont décrites ci-dessous. Ces phases ne sont en général pas spécifiques au C++, et même si les différents outils de programmation peuvent les cacher, le processus de génération des exécutables se déroule toujours selon les principes qui suivent. Au début de la génération de l’exécutable, on ne dispose que des fichiers sources du programme, écrit en C, C++ ou tout autre langage (ce qui suit n’est pas spécifique au C/C++). En général, la première étape est le traitement des fichiers sources avant compilation. Dans le cas du C et du C++, il s’agit des opérations effectuées par le préprocesseur (remplacement de macros, suppression de texte, inclusion de fichiers…).

Vient ensuite la compilation séparée, qui est le fait de compiler séparément les fichiers sources. Le résultat de la compilation d’un fichier source est généralement un fichier en assembleur, c’est-à-dire le langage décrivant les instructions du microprocesseur de la machine cible pour laquelle le programme est destiné. Les fichiers en assembleur peuvent être traduits directement en ce que l’on appelle des fichiers objets. Les fichiers objets contiennent la traduction du code assembleur en langage machine. Ils contiennent aussi d’autres informations, par exemple les données initialisées et les informations qui seront utilisées lors de la création du fichier exécutable à partir de tous les fichiers objets générés.

Les fichiers objets peuvent être regroupés en bibliothèques statiques, afin de rassembler un certain nombre de fonctionnalités qui seront utilisées ultérieurement. Enfin, l’étape finale du processus de compilation est le regroupement de toutes les données et de tout le code des fichiers objets du programme et des bibliothèques (fonctions de la bibliothèque C standard et des autres bibliothèques complémentaires), ainsi que la résolution des références inter-fichiers. Cette étape est appelée édition de liens (« linking » en anglais). Le résultat de l’édition de liens est le fichier image, qui pourra être chargé en mémoire par le système d’exploitation. Les fichiers exécutables et les bibliothèques dynamiques sont des exemples de fichiers image.

Formation programmez en C++ et développez vos applicationsTélécharger le cours complet

Télécharger aussi :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *