Programmer sous GNU/LINUX
Ce TP introductif à la programmation en C sous GNU/Linux vous familiarise avec la syntaxe du langage C, l'utilisation du compilateur gcc, le préprocesseur cpp, le débogueur, la compilation séparée avec make, ainsi que l'utilisation des bibliothèques. Il nécessite un environnement GNU/Linux avec gcc et les outils associés.
D'après le document Programmer sous GNU/LINUX
Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source
Programming, Math · PDF · 5 pages
Afficher l'aperçu du document
Ce TP introductif à la programmation en C sous GNU/Linux vous familiarise avec la syntaxe du langage C, l'utilisation du compilateur gcc, le préprocesseur cpp, le débogueur, la compilation séparée avec make, ainsi que l'utilisation des bibliothèques. Il nécessite un environnement GNU/Linux avec gcc et les outils associés.
Objectifs
- Écrire et compiler un programme C simple calculant la factorielle.
- Utiliser un débogueur pour suivre l'exécution pas à pas.
- Comprendre et appliquer la compilation conditionnelle avec le préprocesseur.
- Mettre en œuvre la compilation séparée et utiliser make.
- Créer et utiliser des bibliothèques statiques et dynamiques.
- Découvrir d'autres outils d'analyse et de profilage du code C.
Prérequis et installation
- Un système GNU/Linux avec gcc installé.
- Connaissances de base en langage C.
- Accès à un terminal et éditeur de texte.
- Outils supplémentaires : débogueur (xxgdb ou ddd), make, lclint, gprof, nm.
Exercice 1 : Calcul de la factorielle
Écrivez un programme en C qui calcule la factorielle de 10 et affiche le résultat. Définissez la fonction suivante dans un fichier nommé factorielle.c :
unsigned int factorielle (unsigned int n)
{
unsigned int i = 1, res = 1;
while (i <= n)
res = res * i++;
return res;
}
Compilez ce programme avec la commande :
% gcc -g -Wall -Werror -ansi -pedantic -o factorielle factorielle.c
Les options utilisées signifient :
-ansiet-pedantic: respecter strictement la norme ANSI C.-Wall: afficher tous les avertissements.-Werror: traiter les avertissements comme des erreurs.-g: inclure les informations pour le débogueur.-o factorielle: nommer l'exécutablefactorielle.
Si la compilation réussit, exécutez le programme :
% ./factorielle
3628800
Le résultat attendu est 3628800, la factorielle de 10.
Exercice 2 : Utilisation d'un débogueur
1. Placez un point d'arrêt avant l'appel à la fonction factorielle() dans la fonction main().
2. Lancez le programme en mode pas à pas (avec step pour entrer dans la fonction, next pour passer les appels).
3. Affichez les valeurs des variables locales res et i avec la commande display. Au début, ces variables ne sont pas initialisées et peuvent contenir n'importe quelle valeur.
4. Continuez l'exécution pas à pas pour observer l'évolution de res et i au fil des itérations de la boucle.
Relancez ensuite le programme avec un point d'arrêt identique et modifiez la valeur de n dans main() :
(xxgdb) set n=12
(xxgdb) cont
Le programme calcule alors la factorielle de 12. Recommencez avec n=13 et observez que le résultat ne correspond pas à 13 fois la factorielle de 12, en raison de la limite de 32 bits des entiers sur cette machine.
Exercice 3 : Compilation conditionnelle et préprocesseur
Le préprocesseur permet de sélectionner des portions de code à compiler selon des conditions. Par exemple :
#if ARCH = i386
/* code pour un intel i386 */
#endif
#if ARCH = alpha
/* code pour un DEC Alpha */
#endif
Question 1 : Renommez la fonction factorielle() en factorielle_iterative() et écrivez la fonction récursive :
unsigned int factorielle_recursive (unsigned int n);
Placez les deux versions dans une directive conditionnelle :
#ifdef RECURSIVE
unsigned int
factorielle_recursive (unsigned int n)
{
...
}
unsigned int
factorielle (unsigned int n)
{
return factorielle_recursive (n);
}
#else
unsigned int
factorielle_iterative (unsigned int n)
{
...
}
unsigned int
factorielle(unsigned int n)
{
return factorielle_iterative (n);
}
#endif
Question 2 : Définissez la macro RECURSIVE soit dans le fichier source avec #define RECURSIVE, soit lors de la compilation avec l'option -D RECURSIVE. Vérifiez le préprocessing avec :
% gcc -E -P factorielle.c | grep -v '^[ ]*$' | more
% gcc -E -P -D RECURSIVE factorielle.c | grep -v '^[ ]*$'
Vous verrez que la version compilée change selon la définition de la macro.
Question 3 : Compilez la version récursive et déboguez-la :
% gcc -D RECURSIVE -g -Wall -Werror -ansi -pedantic -o factorielle factorielle.c
% xxgdb factorielle
Placez un point d'arrêt avant le return de factorielle_recursive(), lancez l'exécution, puis avancez dans les appels récursifs avec step. Utilisez la commande bt pour afficher la pile d'appels et frame n pour naviguer dans un cadre d'appel particulier. Par exemple :
(xxgdb) print n
$1 = 4
(xxgdb) frame 3
#3 0x804840d in factorielle_recursive (n=7) at factorielle.c:5
(xxgdb) print n
$2 = 7
Exercice 4 : Compilation séparée et utilisation de make
Question 1 : Séparez le programme en deux fichiers sources :
factorielle.c: définitions des fonctionsfactorielle_iterative(),factorielle_recursive()etfactorielle().main.c: fonctionmain()uniquement.
Créez un fichier d'en-tête factorielle.h contenant :
extern unsigned int factorielle(unsigned int);
Incluez-le dans main.c :
#include <stdio.h>
#include "factorielle.h"
...
Compilez sans make avec :
% gcc -c -Wall -Werror -ansi -pedantic factorielle.c
% gcc -c -Wall -Werror -ansi -pedantic main.c
% gcc -Wall -Werror -ansi -pedantic -o factorielle factorielle.o main.o
L'option -c génère les fichiers objets sans édition de liens.
Question 2 : Créez un fichier Makefile avec le contenu :
CC = gcc
CFLAGS = -Wall -Werror -ansi -pedantic
CFLAGS += -g
factorielle: factorielle.o main.o
$(CC) $(CFLAGS) -o factorielle factorielle.o main.o
factorielle.o: factorielle.c
$(CC) -c $(CFLAGS) factorielle.c
main.o: main.c
$(CC) -c $(CFLAGS) main.c
Modifiez la date de factorielle.c et lancez :
% touch factorielle.c
% make
Seules les étapes nécessaires sont exécutées.
Question 3 : Ajoutez au Makefile les cibles clean et realclean :
.PHONY: clean realclean
clean:
$(RM) factorielle.o main.o
realclean : clean
$(RM) factorielle
Ces cibles permettent de supprimer les fichiers intermédiaires et l'exécutable.
Exercice 5 : Bibliothèques statique et dynamique
Question 1 : Modifiez le Makefile pour créer une bibliothèque statique libfact.a et l'utiliser dans le programme factorielle.
Question 2 : Modifiez le Makefile pour créer une bibliothèque dynamique libfact.so et l'utiliser dans le programme factorielle.
Exercice 6 : Autres outils
- lclint : une version moderne de lint, analyse statique du code C, disponible sur le réseau enseignement. Essayez la commande
lclintsur vos sources. - gprof : outil de profilage. Compilez avec
-pg, exécutez le programme pour générergmon.out, puis analysez avecgprofpour visualiser l'arbre des appels et le temps CPU passé dans chaque fonction. - nm : liste les symboles dans un fichier objet ou exécutable, permettant d'identifier variables et fonctions définies ou utilisées.
Résultats attendus
- Affichage correct de la factorielle de 10 : 3628800.
- Compilation sans erreurs ni warnings avec les options strictes.
- Fonctionnement correct du débogueur, avec observation des variables locales et pile d'appels.
- Commutation entre versions itérative et récursive via la macro
RECURSIVE. - Compilation séparée fonctionnelle, avec recompilation partielle via make.
- Création et utilisation réussies des bibliothèques statique et dynamique.
Pièges courants
- Oublier un opérateur dans la boucle
while(exemple :while (i n)au lieu dewhile (i <= n)). - Ignorer les warnings, qui sont traités comme erreurs avec
-Werror. - Ne pas inclure correctement les fichiers d'en-tête, ou utiliser des guillemets au lieu des chevrons pour les fichiers locaux.
- Ne pas définir la macro
RECURSIVEpour tester la version récursive. - Confusion entre compilation complète et compilation séparée, oubli de l'option
-c. - Ne pas utiliser les cibles
cleanetrealcleandans le Makefile pour gérer les fichiers intermédiaires. - Limite de taille des entiers 32 bits, entraînant des résultats incorrects pour les factorielles supérieures à 12.
Commentaires
Aucun commentaire pour le moment. Posez la première question.