Vous êtes sur la page 1sur 8

Page 1 of 8

Chapitre 2 : Etapes de compilation d'un


programme en C
Contents
Introduction............................................................................................................................................. 1
I. Le traitement par le préprocesseur................................................................................................. 1
1. Enlèvement de commentaires .................................................................................................... 2
2. Inclusion de fichiers ..................................................................................................................... 2
3. Substitutions................................................................................................................................ 2
4. L’instruction undef ...................................................................................................................... 4
5. Les macros prédéfinies ................................................................................................................ 4
6. Compilation conditionnelle ......................................................................................................... 5
a. Incorporation liée à l’existence de symboles .......................................................................... 5
b. Incorporation liée à la valeur d’une expression ...................................................................... 6
II. La compilation ................................................................................................................................. 6
III. L’assembleur................................................................................................................................ 6
IV. L’édition de liens ......................................................................................................................... 7
V. Exemples.......................................................................................................................................... 8

Introduction
La compilation consiste à traduire le programme source (ou le contenu d’un fichier source) en
langage machine, en faisant appel à un programme nommé compilateur. La compilation se
décompose en fait en 4 phases successives : Le préprocesseur, la compilation, l’assemblage, l’édition
des liens.

I. Le traitement par le préprocesseur


• Le préprocesseur est un programme qui est exécuté automatiquement avant la compilation et
qui transforme votre fichier source à partir d’un certain nombre de directives.
• Ces dernières, contrairement à ce qui se produit pour les instructions du langage C, sont écrites
sur des lignes distinctes du reste du programme ; elles sont toujours introduites par un mot
précis commençant par le caractère # (#include, #define…)
● Le préprocesseur effectue des transformations purement textuelles en traitant ces directives
pour obtenir le code source brut.
• Ce traitement peut être :
o Enlever des commentaires
o l’inclusion de fichiers (directive #include) ;

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 2 of 8

o la substitution de symboles et de macros (directive #define, #undef) ;


o la compilation conditionnelle : #if, #ifdef, #ifndef, #else, #endif

1. Enlèvement de commentaires
Les commentaires sont destinés à faciliter la compréhension du code source lors de la relecture. Ils
ne sont d’aucune utilité au compilateur, et il est naturel qu’ils n’apparaissent pas dans le code source
qui lui est destiné. Par conséquent, le pré-processeur retire les caractères compris entre /* et */.

2. Inclusion de fichiers
• La directive #include sert à inclure les fichiers, des modules que l’on va utiliser ou écrire.
Le pré-processeur fait simplement un copier-coller du contenu du fichier inclut dans le fichier
contenant le #include.
Cette directive possède deux syntaxes:
#include <nom_fichier>

o Recherche le fichier mentionné dans un emplacement (chemin, répertoire) défini par


l’implémentation. Cette syntaxe entraîne la recherche dans un catalogue prédéfini
correspondant à l’installation du compilateur.
o est utilisée pour les fichiers en-tête correspondant à la bibliothèque standard.
#include "repertoire/nom_fichier"
o Si le nom de fichier est entouré par des guillemets, recherche le fichier mentionné dans
le même emplacement (chemin, répertoire) que celui où se trouve le programme source.
Cette syntaxe est utilisée pour les fichiers créés par le programmeur.
Exemples :

o #include <stdio.h> /*(permet d’utiliser les fonctions printf() et scanf())*/

o #include <math.h> /*(permet d’utiliser les fonctions mathématiques)*/

3. Substitutions
• la directive #define sert à définir des symboles et des macros (c’est à dire des bout de code
qui seront recopiées tels-quels dans le code C)
• Exemples de définitions de symboles:
o #define TAILLE 5
 demande de substituer au symbole TAILLE (constante) par le texte 5, et cela chaque
fois que ce symbole apparaîtra dans la suite du fichier source.
o #define entier int
 placée en début de programme, permettra d’écrire en français les déclarations de
variables entières.
 Par exemple, entier a, b ; sera remplacée par : int a, b ;
o #define bonjour printf("bonjour")
o ça permet de résumer en un seul mot une instruction en C : bonjour est remplacé par
printf("bonjour")

Exemples de définition de macros


o La définition de macros ressemble à la définition de symboles mais elle fait intervenir la
notion de paramètres.
o #define carre(a) a*a

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 3 of 8

 Tous les symboles carre(x) seront remplacés par x*x par le préprocesseur
o #define dif(a,b) a-b
 Dans cet exemple, la macro contient deux paramètres

Attention : contrairement à une instruction du langage C, les instructions du préprocesseur ne


doivent pas être terminées par un caractère « ; ».

Attention : le programme n'est pas compilé durant le traitement du pré-processeur. Si des erreurs
existent, elles seront toujours présentes après la phase de pré-processing. Le pré-processeur ne fait
que réécrire le programme selon des règles que vous précisez.

Exemple :

#include <stdio.h>
#include <stdlib.h>
/* Définition de quelques macros */
#define FALSE 0 /*simuler les variabes booléennes qui
n’existaient pas dans les premières
versions du C*/
#define TRUE 1
#define BOOL int
#define MINI( a, b ) ((a)<(b) ? (a) : (b))
#define MAXI( a, b ) ((a)>(b) ? (a) : (b))

/* Exemple d'utilisation de ces macros */


int main() {
BOOL state = TRUE;
if ( state == FALSE ) {
printf( "Maximum(3, 5) == %d", MAXI( 3, 5 ) );
} else {
printf( "Minimum(3, 5) == %d", MINI( 3, 5 ) );
}
return EXIT_SUCCESS;
}
Le code de la fonction main après traitement par le préprocesseur est :

int main() {

int state = 1;

if ( state == 0 ) {
printf( "Maximum(3, 5) == %d", ((3)>(5) ? (3) : (5)) );
} else {
printf( "Minimum(3, 5) == %d", ((3)<(5) ? (3) : (5)) );
}

return 0;
}

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 4 of 8

4. L’instruction undef
Cette instruction permet d'annuler une définition de macro. Il suffit juste de spécifier le nom de la
macro à invalider et ce directement après l'instruction.

#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 123;

#define a 456
printf( "a = %d\n", a );
#undef a

printf( "a = %d\n", a );


return EXIT_SUCCESS;
}
La compilation et l’exécution de ce code donnera :

a = 456
a = 123

5. Les macros prédéfinies


Il existe un certain nombre de macros qui sont prédéfinies. Ces macros ne peuvent en aucun cas être
supprimées ou altérées.

Nom des
Développement de la macro associée.
macros

__LINE__ Se développe en une valeur numérique associée au numéro de la ligne


courante dans le code du programme.
__FILE__ Cette macro sera remplacée par le nom du fichier en cours de traitement.
__DATE__ Celle-ci se transformera en une chaîne de caractères contenant la date de
traitement du fichier sous un format "Mmm jj aaaa".
__TIME__ De même, se transformera en un chaîne représentant l'heure de traitement
du fichier sous le format "hh:mm:ss".
Cette macro n'est censée être définie uniquement que dans les
__STDC__ implémentations respectant la norme ANSI. Si c'est le cas, elle doit de plus
valoir 1.

Attention : les deux caractères _ (underscore) font partie du nom de la macro

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 5 of 8

6. Compilation conditionnelle
Un certain nombre de directives permettent de sélectionner (inclusion ou exclusion) des
portions du fichier source dans le texte qui est analysé par le préprocesseur.
Cette sélection se fait à partir des lignes de directives suivantes : #if, #ifdef, #ifndef, #else, #endif
Ces directives se classent en deux catégories en fonction de la condition qui régit l’incorporation :
 existence ou inexistence de symboles ;
 valeur d’une expression.

a. Incorporation liée à l’existence de symboles


Exemple 1:

#ifdef PI
instructions 1 ...
#else
instructions 2 ...
#endif
Dans cet exemple, si la constante PI est définie (c’est à dire #define PI existant), alors la partie
instructions1 sera incluse dans le code, sinon instructions 2).

Exemple 2:

#define VX #define VX
..... .....
#ifdef VX #ifndef VX
instructions 1 instructions 1
#else #else
instructions 2 instructions 2
#endif #endif

Remarque:

Il existe un opérateur noté defined qu’on peut utiliser dans les exemples précédents.

#if defined(PI)
instructions 1 ...
#else
instructions 2 ...
#endif

Résumé:
#if defined identifier #ifdef identifier

#if ! defined identifier #ifndef identifier

Correspondances entre les directives #if, #ifdef et #ifndef

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 6 of 8

Remarque : le ! est un opérateur du pré-processeur qui renvoie 1 si son opérande est 0 et renvoie 0
dans tous les autres cas.

b. Incorporation liée à la valeur d’une expression

#define CODE 1
.....
#if CODE == 1
instructions 1
#endif
#if CODE == 2
instructions 2
#endif

Dans cet exemple, ce sont les instructions 1 qui seront incorporées par le préprocesseur. Mais il
s’agirait des instructions 2 si nous remplacions la première directive par : #define CODE 2

Notez qu’il existe également une directive #elif qui permet de condenser les choix imbriqués.
Par exemple, nos précédentes instructions pourraient s’écrire :

#define CODE 1
.....
#if CODE == 1
instructions 1
#elif CODE == 2
instructions 2
#endif

II. La compilation
Au cours de cette étape, le fichier engendré par le préprocesseur est traduit en assembleur, c'est à
dire en une suite d'instructions qui sont chacune associées à une fonctionnalité du microprocesseur
(faire une addition, une comparaison, etc.).

Remarque :

Le compilateur C a pour particularité de faire de la compilation séparée : cela signifie que chaque
fichier source est compilé sans regarder les autres fichiers, même s’ils font partie du même
programme. Pour compiler un fichier C, le compilateur a juste besoin de connaitre les prototypes de
toutes les fonctions utilisées dans ce fichier, mais il n’a pas besoin d’avoir à sa disposition le code de
ces fonctions externes. Les prototypes des fonctions sont définies dans des fichiers .h, qui sont inclus
par le pré-processeur dans le fichier C qui les utilise via la directive #include

III. L’assembleur
L’assembleur prend un fichier écrit en langage assembleur et le traduit en code binaire (langage
machine) : instructions directement compréhensibles par le processeur.

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 7 of 8

Le fichier produit par l'assemblage est appelé fichier objet (extension .o) qui est totalement
incompréhensible par l’humain.

IV. L’édition de liens


Un programme est souvent séparé en plusieurs fichiers source, pour des raisons de clarté mais aussi
parce qu’il fait généralement appel à des librairies de fonctions standard déjà écrites. L'éditeur de
liens prend les fichiers objet du programme pour les assembler et produire un exécutable. Ici, le code
de toutes les fonctions doit être présent et sera inséré dans le programme. Si le code des fonctions
que vous utilisez n'est pas dans vos fichiers objet, il va les chercher dans les bibliothèques que vous
lui aurez indiquées. S'il ne trouve toujours pas la fonction, il ne peut pas continuer (le programme est
incomplet) et l'édition des liens échouera. En cas de succès, l’édition de liens produit alors un fichier
dit exécutable (extension .exe).

Résumé :

Pour obtenir ces fichiers, voilà les commandes nécessaires :

• gcc –E bonjour.c > bonjour.i


 étape de préprocesseur : produit le fichier bonjour.i
• gcc –S bonjour.i
 on obtient l’assembleur dans bonjour.s
• gcc –c bonjour.s
 on obtient le fichier objet bonjour.o
• gcc bonjour.o -o bonjour
 on obtient l’exécutable bonjour
• ./bonjour
 on exécute le programme

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020


Page 8 of 8

V. Exemples
Exemple 1:

Exemple 2:
Le programme est divisé en trois fichiers :
- La somme i+2 est réalisée par une fonction f, qui est écrite dans le fichier f1.c
- La racine carrée de j est réalisée par une fonction g, qui est écrite dans le fichier f2.c
- Le programme principal qui calcule f(i)*g(j) se trouve dans le fichier p1.c
- On veut construire le programme qui affiche le résultat

© Ichrak Amdouni Programmation Procédurale et Langage C Eniso 2019-2020

Vous aimerez peut-être aussi