Ce document a été produit par HEVEA.
Votre browser peut avoir a être configuré pour afficher correctement
certains symboles.
Reportez-vous à la documentation d'HEVEA.
unsigned int
factorielle (unsigned int n)
{
unsigned int i = 1, res = 1;
while (i n)
res = res * i++;
return res;
}
qui calcule la factorielle de n de façon itérative.
On placera le source de ce programme dans le fichier source
factorielle.c ;
% gcc -g -Wall -Werror -ansi -pedantic -o factorielle factorielle.c
indique que dans la fonction factorielle du fichier source factorielle.c, il y a une erreur. C'est une erreur de syntaxe à la ligne 6 (while (i n)) où il manque un opérateur entre i et n. La seconde erreur est une admonestation (warning) à la ligne 11 (main()), où le type retourné par la fonction main a été fixé par défaut à int. Lisez donc toujours bien les messages d'erreurs. Exécutez ensuite ce programme.% gcc -g -Wall -Werror -ansi -pedantic -o factorielle factorielle.c factorielle.c: In function `factorielle': factorielle.c:6: parse error before `n' cc1: warnings being treated as errors factorielle.c: At top level: factorielle.c:11: warning: return-type defaults to `int'
% factorielle 362880
et terminez son exécution (cont). Le programme a bien calculé la factorielle de 12, et non pas de 10. Recommencez avec n=13, et vérifiez que le résultat n'est pas égal à 13 fois le précédent. Les entiers de type int ne font bien que 32 bits sur cette machine.(xxgdb) set n=12
#if ARCH = i386 /* code pour un intel i386 */ #endif #if ARCH = alpha /* code pour un DEC Alpha */ #endif
qui calcule la factorielle de n de façon récursive. Placez les corps de ces fonctions dans une directive #ifdef/#endif de la manière suivante :unsigned int factorielle_recursive (unsigned int n);
#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
De cette manière, si la macro RECURSIVE est définie,
seule la fonction factorielle_recursive() sera définie,
et l'appel à la fonction factorielle() sera un appel à
factorielle_recursive(). Sinon seule
factorielle_iterative() est définie, et un appel à
factorielle sera un appel à
factorielle_iterative().
Vous voyez apparaître les déclarations de types, variables et fonctions standard, puis celles contenues dans% gcc -E -P factorielle.c | grep -v '^[ ]*$' | more
<stdio.h>,
et enfin la définition de factorielle_iterative(),
factorielle() et main(). Recommencez en
définissant la macro RECURSIVE :
C'est bien maintenant la version récursive qui est définie.% gcc -E -P -D RECURSIVE factorielle.c | grep -v '^[ ]*$'
% gcc -D RECURSIVE -g -Wall -Werror -ansi -pedantic -o factorielle factorielle.c % xxgdb factorielle
(xxgdb) print n $1 = 4 (xxgdb) frame 3 #3 0x804840d in factorielle_recursive (n=7) at factorielle.c:5 (xxgdb) print n $2 = 7
et incluez ce fichier dans main.c :extern unsigned int factorielle(unsigned int);
Remarquez l'utilisation des doubles quotes pour indiquer au compilateur de chercher le fichier d'entêtes factorielle.h dans le répertoire courant en premier. Sans utiliser make, pour compiler le programme, il faut exécuter les commandes suivantes:#include <stdio.h> #include "factorielle.h" ...
% 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 de gcc permet de spécifier au
compilateur de ne pas faire l'édition de liens, et de ne
générer que les fichiers objets .o.
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
Les lignes correspondantes aux commandes à exécuter commencent par
une tabulation. Lancez la compilation par la commande
make (ou make factorielle si la première règle
de dépendance ne concerne pas factorielle). Les trois
compilations sont automatiquement exécutées. En modifiant la date
du fichier factorielle.c, et en recompilant,
% touch factorielle.c % makeseule la compilation de factorielle.c et l'édition de liens sont exécutées, le fichier main.c étant resté inchangé.
CC = gcc
CFLAGS = -Wall -Werror -ansi -pedantic
CFLAGS += -g
factorielle: factorielle.o main.o
$(CC) $(CFLAGS) -o factorielle factorielle.o main.o
.PHONY: clean realclean
clean:
$(RM) factorielle.o main.o
realclean : clean
$(RM) factorielle
Partisan du moindre effort (et de la moindre erreur), on peut
rassembler l'ensemble des fichiers .o dans une
variable OBJ et utiliser la variable automatique
$@ :
CC = gcc
CFLAGS = -Wall -Werror -ansi -pedantic
CFLAGS += -g
OBJ = factorielle.o main.o
factorielle: $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
.PHONY: clean realclean
clean:
$(RM) $(OBJ)
realclean : clean
$(RM) factorielle
On termine alors la séance de TP par :
% make realclean rm -f factorielle.o main.o rm -f factorielle
Ce document a été traduit de LATEX par HEVEA.