2.1 Premier programme en C
Commençons par un grand classique. Ainsi, on se propose tout
d'abord d'afficher quelque chose à l'écran. Le bout de code
suivant va réaliser cette tâche.
#include <stdio.h>
/* ceci est un commentaire */
/* ceci est un commentaire
sur plusieurs ligne */
int main(void) {
/* pas de declaration
de variable locale */
printf("Salut le monde\n") ;
return 0 ; /* instruction de retour */
}
Dans cette exemple, on peut remarquer que les expressions en C se
terminent par un point-virgule et qu'un commentaire commence par /* et
se termine par */. Ainsi, on peut placer la ligne
suivante
/* Ceci est un commentaire */
dans un programme C sans affecter son comportement.
Avant d'exécuter notre programme, précisons quelques points de
théorie.
2.1.1 C est un langage compilé
Cela signifie qu'un programme C est décrit par un fichier texte
appelé fichier source. Ce fichier n'est pas exécutable
par le microprocesseur, il faut le traduire en langage machine. Cette
opération est effectuée par un programme appelé
compilateur. La compilation se décompose en 4 phases
successives :
-
Le traitement par le préprocesseur :le fichier source est analysé par un programme appelé
préprocesseur qui effectue des transformations purement
textuelles (remplacement de chaînes de caractères, inclusion
d'autres fichiers source, etc.) ;
- 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 chacunes associées à une fonctionnalité du
microprocesseur (faire une addition, une comparaison, etc.) ;
- L'assemblage : cette opération transforme le code
assembleur en un fichier binaire, c'est à dire en
instructions directement compréhensibles par le processeur. Le
fichier produit par l'assemblage est appelé fichier
objet ;
- L'édition de liens : un programme est souvent
séparé en plusieurs fichiers source (ceci permet d'utiliser des
librairies de fonctions standard déjà écrites comme les
fonctions d'affichage par exemple). Une fois le code source
assemblé, il faut donc lier entre eux les différents
fichiers objets. L'édition de liens produit alors un fichier
exécutable.
Comme rien ne vaut la pratique, nous allons effectuer les tâches
décrites ci-dessus.
2.1.2 Compilation par la pratique
Édition du fichier source
Pour éditer le fichier source, nous allons utiliser le logiciel
emacs que l'on lance depuis le shell par la commande
$ emacs.
Pour éditer un fichier source, utiliser la barre de menu d'emacs :
File -> Open,
puis indiquer un nom de fichier avec la lettre c pour extension ---
foo.c par exemple. Emacs vous présente un buffer
dans lequel vous pouvez créer votre fichier source (dans notre cas,
il s'agit de la procédure permettant l'affichage d'un message
présenté en début de section 2.1)
Compilation.
Une fois que l'édition de votre fichier source est terminée, vous
pouvez le compiler. Dans notre cas, nous utilisons le compilateur
gcc. On utilise dans le shell la commande $ gcc
foo.c et on obtient directement le fichier exécutable
a.out. Le nom du fichier exécutable peut être
spécifié en utilisant l'option -o du compilateur
(gcc -o nom_de_l_executable foo.c). De plus, l'option
-Wall permet d'afficher tous les avertissements émis par le
compilateur. Les options -ansi -pedantic permettent de faire
signaler tout ce qui s'écarte de la norme dans votre programme.
Exécution.
Enfin pour finir, on peut exécuter à partir du shell le fichier
résultant par la commande $ a.out.
Expérimentation
On peut suivre les étapes de la compilation en utilisant les options
adéquates du gnu c compiler. Ainsi.
-
Pour constater le travail du préprocesseur, utilisez la
commande gcc -E foo.c > res.txt et éditez le fichier
res.txt.
- Pour interrompre la compilation avant l'assemblage, il suffit
d'utiliser l'option -S du compilateur. Un fichier
foo.s est engendré et on peut en lire l'assembleur en
l'éditant.
- Pour obtenir, un fichier objet --- foo.o dans notre
exemple --- on peut utiliser l'option -c du compilateur.
L'utilitaire objdump permet de décoder le fichier objet.
Ainsi, la commande objdump -S foo.o affiche la succession
d'octets hexadécimals constituant le fichier et leur traduction en
langage assembleur.
Plus généralement, la commande man gcc fournit le manuel
du compilateur gnu.
Remarque. En guise de conclusion, il faut bien retenir que
seuls les fichiers source doivent être archivés.
Exercice 2.0 --- Valeur de retour.
Considérons le programme :
int main(void){
return 5 ;
}
Ce programme est uniquement constitué par la fonction principale
main qui ne prend aucun paramètre et retourne l'entier 5.
Compiler ce programme afin d'obtenir un fichier
exécutable foo. Vous pouvez lancer son exécution depuis
le shell et récupérer sa valeur de retour par la commande
interne echo en affichant la variable ?.
% foo
% echo $?
Que constatez vous ? Confirmez votre intuition en faisant varier la
valeur de retour.
Exercice 2.1 --- Étapes de la compilation.
Nous allons utiliser le programme suivant :
#include <stdio.h>
#define MAX 3
const int bar_constante = MAX ;
int foo_global = 1 ;
extern int bar ;
int main(void) {
int foo_local = 2 ;
printf("Salut le monde~: %d \n",bar + foo_global + foo_local) ;
return 0 ;
}
La compilation se fait avec gcc dont l'aide est disponible en ligne.
Cette aide est structurée en section ; les informations nous
intéressant dans cet exercice se trouvent dans la section
OPTIONS, sous-section Options contrôlant le type de
sortie après la description des options concernant les langages
compris par gcc.
Questions.
-
Combien de lignes non vide le préprocesseur a-t-il ajouté
à votre code ? (Ne comptez pas, utilisez des outils shell dont wc).
- Qu'est devenu la ligne
#include <stdio.h> ? Que sont
devenus les commentaires ? Comment a été traitée la chaîne
ce caractères MAX ?
- Pour examiner un fichier objet, vous pouvez utiliser
objdump ou nm. Dans la table des symboles, quels
sont les références qui seront résolues par l'éditeur de
liens ? En utilisant l'utilitaire ldd, déterminer quels
sont les fichiers objets utilisés par votre exécutable ? (Pour
achever la compilation supprimer la variable externe bar de
votre code).
Pour tout commentaire : Alexandre Sedoglavic.