Cette section présente succinctement les éléments essentiels du Langage C en donnant un maximum d'exemples adaptés au développement sur système spécialisé.
On utilise un exemple de programme presque aussi connu que le très fameux «Hello, World!» ; le calcul des nombres de Fibonacci. On commence par présenter le listing complet, puis on détaille les éléments de la syntaxe du Langage C.
Le même programme est présenté sous plusieurs formes différentes en fonction du contexte de développement.
Exemple 3. Calcul des nombres de Fibonacci sur GNU/Linux avec GCC
01: /* $Id: gcc_fibonacci_single.c 1129 2007-05-07 15:07:52Z latu $
02: * Un programme simple pour calculer les n premiers nombres de Fibonacci */
03:
04: #include <stdio.h>
05: #include <stdlib.h>
06:
07: #define MAX_FIB 49
08:
09: main() {
10:
11: int n, i;
12: unsigned int nombrePrecedent, nombreCourant, fibonacci;
13:
14:
15: printf("Saisir le nombre de calculs de Fibonacci(n) :\n");
16: scanf("%d", &n);
17: if (n >= MAX_FIB) {
18: printf("Fibonacci(%d) depasse la capacite d'un mot de 32 bits\n", n);
19: exit(1);
20: }
21:
22: nombrePrecedent = 0;
23: nombreCourant = 1;
24: for (i = 0; i < n; i++) {
25: if (i > 1) {
26: fibonacci = nombrePrecedent + nombreCourant;
27: nombrePrecedent = nombreCourant;
28: nombreCourant = fibonacci;
29: printf("Fibonacci (%d) = %u\n", i, fibonacci);
30: }
31: else
32: printf("Fibonacci (%d) = %u\n", i, i);
33: }
34: }
Voici un exemple d'exécution du programme gcc_fibonacci_single.c :
$ ./gcc_fibonacci_single.out Saisir le nombre de calculs de Fibonacci(n) : 11 Fibonacci (0) = 0 Fibonacci (1) = 1 Fibonacci (2) = 1 Fibonacci (3) = 2 Fibonacci (4) = 3 Fibonacci (5) = 5 Fibonacci (6) = 8 Fibonacci (7) = 13 Fibonacci (8) = 21 Fibonacci (9) = 34 Fibonacci (10) = 55
Comme dans le cas du premier programme présenté, le code source du programme destiné au microcontrôleur MSC1210 inclut le pilotage de l'interface série. Dans ce contexte de développement, on ne dispose pas de système d'exploitation.
Exemple 4. Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC
01: #include <stdio.h>
02: #include <stdlib.h>
03: #include <msc1210.h>
04: #include "ser_msc1210.h"
05:
06: #define MAX_FIB 49
07:
08: // surdefinition du sous-programme putchar
09: void putchar(char c) {
10: ser_putc(c);
11: }
12:
13: void main(void) {
14:
15: unsigned char s[3] = {'\0','\0','\0'};
16: int n, i;
17: unsigned long nombrePrecedent, nombreCourant, fibonacci;
18:
19: // Appuyer sur <Entree> pour ajuster automatiquement
20: // le debit de la liaison
21: autobaud();
22: EA=1;
23:
24: do {
25: printf("Saisir le nombre de calculs de Fibonacci :\r\n");
26: ser_gets_echo(s, 2);
27: n = atoi(s);
28: if (n >= MAX_FIB)
29: printf("\nFibonacci(%d) depasse la capacite d'un mot de 32 bits\r\n", n);
30: } while (n >= MAX_FIB);
31:
32: printf("\r\n\n");
33: nombrePrecedent = 0;
34: nombreCourant = 1;
35: for (i = 0; i < n; i++) {
36: if (i > 1) {
37: fibonacci = nombrePrecedent + nombreCourant;
38: nombrePrecedent = nombreCourant;
39: nombreCourant = fibonacci;
40: printf("Fibonacci (%d) = %lu\r\n", i, fibonacci);
41: }
42: else
43: printf("Fibonacci (%d) = %d\r\n", i, i);
44: }
45: while(1);
46: }
Voici un exemple de résultat d'exécution du programme sdcc_fibonacci_single.c :
MSC1210 Ver:000305F10 >M0000 ok >M8000 ok >E >Saisir le nombre de calculs de Fibonacci : 11 Fibonacci (0) = 0 Fibonacci (1) = 1 Fibonacci (2) = 1 Fibonacci (3) = 2 Fibonacci (4) = 3 Fibonacci (5) = 5 Fibonacci (6) = 8 Fibonacci (7) = 13 Fibonacci (8) = 21 Fibonacci (9) = 34 Fibonacci (10) = 55
Généralités sur les délimiteurs de syntaxe du Langage C des exemples ci-dessus :
Ils sont repérés par deux slashes
(//) si le texte du commentaire ne comprend qu'une seule ligne.
Ils sont délimités entre les balises /* et */ si le
texte du commentaire comprend plusieurs lignes.
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : les lignes 1 et 2 correspondent à un même commentaire.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : les lignes 8, 19 et 20 sont des commentaires sur une ligne unique.
Elles sont repérées par le caractère dièse en début de ligne :
#include <stdio.h> #define TRUE 1
Ces directives ne sont pas considérées comme faisant partie du code. Elles ne sont donc pas délimitées comme des instructions «classiques».
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 4, 5 et 7.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 1 à 4 puis 6.
Elles sont séparées par le caractère point-virgule :
printf ("Hello,");
printf (" World!");
Dans les deux exemples de référence ci-dessus, on relève que toutes les instructions (déclarations de variables, opérations, etc.) sont délimitées par des caractères ';' à l'exception des directives du préprocesseur.
Ils sont délimités par les caractères accolades ouvertes et fermées :
while(1) {
printf ("Hello,");
printf (" World!");
}
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : les lignes 9 et 34 contiennent les accolades qui délimitent le début et la fin du programme principal.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec
SDCC » : les lignes 24 et 30
délimitent le groupe d'instructions qui doivent être répétées tant que le
test (n >= MAX_FIB) n'est pas satisfait.
En programmation, les données manipulées sont appelées variables ou constantes.
Une variable sert au stockage d'une information en vue de sa réutilisation dans le programme principal et|ou un sous-programme.
Du point de vue gestion de la mémoire (RAM ou Random Access Memory), une variable est une zone mémoire réservée et «étiquetée» avec le nom de cette variable.
Sur une machine avec système d'exploitation, la phase de déclaration d'une variable correspond à une demande de réservation mémoire au gestionnaire de mémoire virtuelle du noyau. Ce gestionnaire doit gérer au mieux ces demandes en fonction des programmes actifs sur le système.
Sur un système spécialisé, c'est au développeur de gérer «manuellement» son espace mémoire. Il n'existe aucune protection contre le débordement de la capacité mémoire.
Du point de vue syntaxique, il existe certaines restrictions dans l'emploi des noms de variables et de constantes. Les caractères de ponctuation ne sont pas utilisables. Le caractère «souligné» (underscore) est considéré comme une lettre ; il est beaucoup utilisé par le préprocesseur.
|
Avertissement |
|---|---|
|
En Langage C, les majuscules et les minuscules sont traitées différemment. On utilise généralement les majuscules pour les définitions de constantes et les minuscules pour les variables. |
Suivant la génération du compilateur utilisé, le nombre de caractère pris en compte pour les noms de variables est plus ou moins limité. Historiquement, cette limite était fixée à 8 bien que l'on puisse en utiliser davantage dans le code source.
Dans les deux exemples ci-dessus, on trouve les déclarations des
variables après l'accolade de début de programme principal (fonction
main()).
Pour représenter les données à manipuler on distingue différents types élémentaires définis dans la syntaxe du langage de programmation. La table ci-dessous donne une liste complète de ces types.
Tableau 1. Types élémentaires du Langage C
| Type de donnée | syntaxe C |
|---|---|
| rien ou vide |
void
|
| caractère |
char
|
| nombre entier court |
short
|
| nombre entier |
int
|
| nombre entier long |
long
|
| nombre entier long double |
long long
|
| nombre réel |
float
|
| nombre réel double |
double
|
| nombre réel long double |
long double
|
À la lecture de la table ci-dessus, on constate que le langage C n'offre
pas de type booléen. Pour autant, la valeur entière 0 correspond à
l'état faux et toutes les autres valeurs entières
correspondent à l'état vrai. La technique usuelle pour
représenter les deux états booléens consiste à définir deux constantes. Voir
Section 7.4, « Constantes ».
En Langage C, si les noms de types sont toujours les mêmes, leurs formats diffèrent suivant les chaînes de développement et les processeurs utilisés. Les deux exemples ci-dessous illustrent ces différences.
Dans le cas de la chaîne de développement GNU utilisée sur PC, il est possible de représenter de très grands nombres réels sur 12 octets soit 96 bits. À l'inverse, il n'est pas possible de représenter une donnée sur moins d'un octet.
Voici le résultat d'un programme utilisant la fonction
sizeof pour chacun des types donnés dans la liste
ci-dessus. Le code source de ce programme est disponible à l'adresse :
gcc_sizeof.tar.bz2.
Exemple 5. Formats des types supportés par GCC
Dimension de chaque type en octets : 'char' : 1 'unsigned char' : 1 'short' : 2 'int' : 4 'long' : 4 'long long' : 8 'float' : 4 'double' : 8 'long double' : 12
Dans le cas du compilateur SDCC et du microcontrôleur
cible MSC1210, il n'est pas possible d'utiliser des nombres
réels au delà de la représentation simple sur 4 octets. La plus petite unité
représentée est le bit même si l'appel à la fonction
sizeof pour ce type produit un résultat surprenant 1
octet pour 1 bit.
Comme avec la chaîne de développement GNU/GCC, voici
le résultat d'un programme utilisant la fonction sizeof
pour chacun des types donnés dans la liste ci-dessus. Le code source de ce
programme est disponible à l'adresse : sdcc_sizeof.tar.bz2.
Exemple 6. Formats des types supportés par SDCC
>Dimension de chaque type en octets : 'char' : 1 'unsigned char' : 1 'short' : 2 'int' : 2 'long' : 4 'long long' : 4 'float' : 4 Attention ! le type bit existe : 'bit' : 1
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 11 et 12. Ce
programme est limité au calcul des nombres de Fibonacci qui ne dépassent pas
la capacité d'un entier représenté sur 32 bits (soit 4 octets). On utilise
donc le type int dans le code source du programme.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec
SDCC » : ligne 16 et 17. Ce
programme est aussi limité à une représentation des nombres entiers sur 32
bits. Avec le compilateur SDCC, c'est le type
long qui est utilisé dans le code source du programme pour
répondre au critère de calcul.
Une constante est une valeur particulière que l'on utilise tout au long du programme. Si cette valeur doit être modifiée, il est préférable de n'avoir qu'une seule ligne à éditer. En terme de maintenabilité du code source, l'utilisation de constantes est très avantageux. De plus, l'utilisation d'une représentation littérale d'une valeur numérique particulière permet de gagner en lisibilité.
En informatique industrielle, on fait un usage «massif» des constantes. En effet tous les registres et les adresses de pilotage des périphériques spécialisés sont représentés à l'aide de constantes. Si ce mode de représentation n'existait pas, on ne pourrait utiliser que des valeurs hexadécimales. Les difficultés de développement des programmes seraient beaucoup plus importantes du fait des confusions possibles entre des valeurs voisines.
En Langage C, les constantes sont en fait des directives destinées au préprocesseur. En effet, comme le rôle du préprocesseur est d'analyser la syntaxe du code source d'un programme, il peut se charger de substituer toutes les occurrences des constantes par leurs valeurs numériques avant de passer à la compilation proprement dite.
Cette technique est très avantageuse puisque l'utilisation des constante ne nécessite aucune réservation en mémoire.
Les deux exemples de programmes montrent la même constante
MAX_FIB déclarée à l'aide de la directive #define.
Cette constante correspond aux rang maximum du nombre de Fibonacci que l'on
peut représenter sur 32 bits.
|
Avertissement |
|---|---|
|
Il faut noter qu'une directive de préprocesseur n'est pas instruction du langage C. C'est la raison pour laquelle on n'utilise pas le caractère ';' comme délimiteur. Cette absence de délimitation ne pose pas de difficulté dans la mesure où on ne peut trouver qu'une directive par ligne. |
Dans les exemples «rituels» de définition de constantes on trouve les deux états booléens :
#define FALSE 0 #define TRUE 1
Le fichier d'en-tête standard limits.h est un
exemple caractéristique de liste de définitions de constantes. Ce fichier
contient les définitions des valeurs entières maximales pour chaque type connu.
Voici un extrait du fichier fourni avec la chaîne
GNU/GCC :
/* Number of bits in a `char'. */ # define CHAR_BIT 8 /* Minimum and maximum values a `signed char' can hold. */ # define SCHAR_MIN (-128) # define SCHAR_MAX 127 /* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ # define UCHAR_MAX 255 /* Minimum and maximum values a `char' can hold. */ # ifdef __CHAR_UNSIGNED__ # define CHAR_MIN 0 # define CHAR_MAX UCHAR_MAX # else # define CHAR_MIN SCHAR_MIN # define CHAR_MAX SCHAR_MAX # endif /* Minimum and maximum values a `signed short int' can hold. */ # define SHRT_MIN (-32768) # define SHRT_MAX 32767 /* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */ # define USHRT_MAX 65535 /* Minimum and maximum values a `signed int' can hold. */ # define INT_MIN (-INT_MAX - 1) # define INT_MAX 2147483647 /* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ # define UINT_MAX 4294967295U
On retrouve les opérateurs usuels en Langage C : +,
-, * et /. À cette liste, il faut
ajouter les éléments propres aux calculs en Langage C.
%
Cet opérateur, noté %, renvoie le reste de la division
entre 2 entiers. Par
exemple : 24 % 9 = 6
++ et --
Pour ajouter une unité à une variable, on utilise l'opérateur
d'incrémentation ++. Pour soustraire une unité à une variable,
on utilise l'opérateur de décrémentation --.
La position de l'opérateur, à la gauche ou à la droite du nom de
variable à une signification particulière. Dans l'expression
'while (++n < 10)', la variable n
sera incrémentée avant d'être comparée à
10. À l'inverse, dans l'expression
'while (n++ < 10)', la variable n
est comparée à 10 avant d'être incrémentée.
En Langage C, on peut appliquer la règle suivante sur les 2 expressions
e1 et e2 :
'(e1) = (e1) (opérateur) (e2)' est
équivalent à '(e1) (opérateur)= (e2)'. Tous les
opérateurs usuels de calculs sont utilisables avec cette règle. Ainsi,
i = i + 2; est équivalent à
i += 2;.
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : à la ligne 24, on trouve un opérateur d'incrémentation du compteur des calculs à effectuer.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : à la ligne 35, on retrouve le même opérateur d'incrémentation.
Ces opérateurs évaluent une condition sur des nombres entiers ou réels et
renvoient une valeur booléenne 0 ou 1.
Tableau 2. Opérateurs relationnels
| Symbole | Opérateur|Condition |
|---|---|
==
|
égalité |
!=
|
différence |
>
|
supérieur à |
<
|
inférieur à |
>=
|
supérieur ou égal à |
<=
|
inférieur ou égal à |
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 17, 24 et 25. Ces opérateurs relationnels sont utilisés pour évaluer une condition sur des valeurs entières dans les calculs.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 28, 30, 35 et 36. Comme dans le cas précédent, on évalue une condition sur des valeurs entières.
Tableau 3. Opérateurs logiques de bits
| Symbole | Opérateur |
|---|---|
&
|
ET
|
|
|
OU (inclusif) |
^
|
OU (exclusif) |
<<
|
décalage à gauche avec remplissage par 0 |
>>
|
décalage à gauche avec remplissage par 0 |
~
|
négation binaire ou complément à 1 |
On utilise l'instruction if-else pour prendre des
décisions. Sa forme générale est :
if ( expression )
instruction1;
else
instruction2;
Si l'expression est vraie, c'est l'instruction 1 qui
est exécutée ; sinon c'est l'instruction 2. Les instructions 1 et 2 peuvent
correspondre à des groupes délimités par des caractères { et
}. La partie else est optionnelle. Si
l'instruction 2 n'existe pas, on n'utilise pas ce mot clé.
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : les lignes 17 à 20
permettent de contrôler que l'utilisateur a bien saisi un nombre de calculs
compatible avec la représentation sur 32 bits du résultat. Si l'utilisateur
saisit une valeur supérieure à la constante MAX_FIB, on affiche
le message d'erreur à la console et l'exécution du programme s'arrête. Les
deux instructions à traiter si l'expression est vraie sont encadrées par des
accolades.
Les lignes 25 à 30 montrent que l'on effectue le calcul des nombres de
Fibonacci pour les valeurs de la variable i strictement
supérieures à 1. Si cette condition n'est pas respectée, on affiche
directement le numéro du calcul comme résultat.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : les lignes 28 et 30 permettent de contrôler que l'utilisateur a bien saisi un nombre de calculs dont les résultats sont correctement représentés sur 32 bits. Dans ce cas, on se contente d'afficher le message d'erreur. On n'utilise pas d'accolades de délimitation de groupe d'instructions.
Comme dans la version GNU/GCC, les lignes 36 à 41 montrent que l'on
effectue le calcul des nombres de Fibonacci pour les valeurs de la variable
i strictement supérieures à 1.
Le traitement des choix multiples peut devenir compliqué lorsque
l'imbrication des blocs d'instructions entre instructions if-else
augmente. C'est pour cette raison qu'une syntaxe particulière à été
introduite : l'instruction switch dont le synoptique est le
suivant.
switch (expression) {
case Valeur1:
// Instructions
break;
case Valeur2:
// Instructions
break;
...
case ValeurN:
// Instructions
break;
default:
// Instructions
}
Le cas classique d'utilisation de l'instruction switch
consiste à programmer un menu à choix multiples. La variable à tester est de
type simple puisqu'il s'agit d'un caractère. Le programme sdcc_switch.c illustre justement l'utilisation d'un
menu suivi d'un test à choix multiples.
Cette structure est très pratique lorsque le résultat de l'expression est de type simple. Lorsque l'on doit évaluer non pas une valeur mais une plage de valeurs, il devient alors plus pratique de retenir un codage du type suivant.
if (condition1) {
// Instructions
}
else if (condition2) {
// Instructions
}
else if (condition3) {
// Instructions
}
// autres conditions
else {
// Instructions
}
Dès lors qu'une ou plusieurs instructions doivent être répétées, on utilise les instructions de boucles disponibles avec le Langage C.
Indépendemment du langage de programmation utilisé, il existe des règles dans l'emploi des boucles.
On emploie la boucle pour (for)
lorsque l'on connaît le nombre d'itérations (ie. le nombre de fois où le
traitement doit être répété dans la boucle).
On emploie la boucle répéter jusqu'à
(do-while) lorsque le corps de la boucle doit être exécuté au
moins une fois.
On emploie la boucle tant que (while)
lorsque le corps de la boucle peut ne pas être exécuté.
La boucle pour (for) en C/C++ comprend
3 champs distincts : l'initialisation, le test de sortie et
l'incrémentation.
for (initialisation; test; incrémentation ) {
// Instructions
}
Les 3 champs définis ci-dessus peuvent être composés à l'aide de n'importe quelle expression C/C++ valide. Ce mode de construction des boucles pour est une originalité importante du C/C++. Il faut cependant être vigilant lors du choix des expressions placées dans ces champs. Un codage trop compact (avec des appels multiples de fonctions par exemple) et|ou des opérations sur des variables sans relations sont très pénalisant pour la mise au point des programmes.
Exemple 3, « Calcul des nombres de Fibonacci sur GNU/Linux avec GCC » : lignes 24 à 30. On trouve
ici un exemple de boucle pour servant à compter le nombre de calculs à
effectuer. La variable i sert au comptage. Elle est initialisée
à 0 dans le premier champ. Le comptage se poursuit tant que la
variable i est strictement inférieur au nombre n. À chaque
«tour» la variable i est incrémentée.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec SDCC » : lignes 35 à 41. On retrouve une syntaxe identique à l'exemple précédent.
Conformément à la règle énoncée ci-dessus, le test est effectué après une
première exécution du corps de la boucle répéter jusqu'à
(do-while).
do {
// Instructions
} while (test);
Comme dans le cas de la boucle précédente, la condition testée peut être composée à l'aide de n'importe quelle expression C/C++ valide. Il est donc préférable de limiter la complexité de cette expression pour faciliter la mise au point des programmes.
Exemple 4, « Calcul des nombres de Fibonacci sur microcontrôleur MSC1210 avec
SDCC » : lignes 24 à 30. Ici, la
saisie du nombre de calculs à effectuer dans la suite du programme est
répétée tant que la valeur est supérieure ou égale à la limite
MAX_FIB. La limite MAX_FIB correspond au maximum
pour lequel le calcul du nombre de Fibonacci est représentable sur 32
bits.
Conformément à la règle énoncée ci-dessus, le test est effectué avant que
le corps de la boucle tant que (while) ne
soit exécuté.
while (test) {
// Instructions
}
Une fois encore ! attention à l'expression de test.
Exemple 9, « Utilisation des fonctions getchar &
putchar avec GCC » : lignes 7 et 8. On trouve ici un
exemple de boucle tant que servant à reproduire à la console le caractère
saisi au clavier tant que celui-ci est différent du code
ASCII EOF. On remarque que la boucle ne
comprend qu'une seule instruction putchar(c). C'est la
raison pour laquelle les accolades ne sont pas nécessaires. Voir Section 7.1, « Délimiteurs ».
Exemple 10, « Utilisation des fonctions getchar &
putchar sur microcontrôleur MSC120 avec SDCC » : lignes 24 à 28. On retrouve le même
traitement que dans l'exemple précédent. On a simplement ajouté un test
nécessaire au saut le ligne lors d'un appui sur la touche
Entrée.
La démarche classique de construction d'un programme informatique veut que l'on découpe un problème complexe en sous-ensembles plus faciles à traiter. Du point de vue du codage, cette démarche se traduit par l'utilisation de sous-programmes correspondant à ces sous-ensembles.
La réutilisation de code est un autre argument pour l'emploi des sous-programmes. Si un même traitement doit être répété à plusieurs reprises dans un programme, il est préférable de le placer dans un sous-programme qui sera appelé autant de fois que nécessaire.
Enfin, le recours aux sous-programmes doit faciliter la lecture et la mise au point des programmes. Un jeu de sous-programmes bien écrit et compréhensible par un grand nombre de programmeurs peut être réutilisé sous forme de bibliothèque.
La bibliothèque glibc est probablement l'exemple
le plus emblématique de bibliothèque partagée. Elle est disponible avec la
totalité des chaînes de développement en Langage C sur tous les systèmes
d'exploitation et pour presque tous les processeurs.
Les fonctions getchar, putchar,
printf et atoi sont quelques exemples
de sous-programmes partagés à l'aide de la bibliothèque
glibc. On les retrouve dans les programmes
d'illustration présentés dans ce document.
Exemple 7. Utilisation d'un sous-programme dans le calcul des nombres de Fibonacci
01: #include <stdio.h>
02: #include <stdlib.h>
03:
04: #define MAX_FIB 49
05:
06: unsigned long iterative_fibonacci(unsigned long f) {
07:
08: unsigned long nombrePrecedent = 0, nombreCourant = 1, fibonacci = 0;
09: int i;
10:
11: if (f > 1 )
12: for (i = 1; i < f; i++) {
13: fibonacci = nombrePrecedent + nombreCourant;
14: nombrePrecedent = nombreCourant;
15: nombreCourant = fibonacci;
16: }
17: else
18: fibonacci = f;
19:
20: return fibonacci;
21: }
22:
23: main() {
24:
25: int n, i;
26:
27: printf("Saisir le nombre de calculs de Fibonacci(n) :\n");
28: scanf("%d", &n);
29: if (n >= MAX_FIB) {
30: printf("Fibonacci(%d) depasse la capacite d'un mot de 32 bits\n", n);
31: exit(1);
32: }
33:
34: for (i = 0; i < n; i++)
35: printf("Fibonacci (%d) = %lu\r\n", i, iterative_fibonacci(i));
36: }
On retrouve des résultats identiques aux précédents avec le programme gcc_fibonacci_iterative.c.
Exemple 8. Utilisation d'un sous-programme dans le calcul des nombres de Fibonacci sur la cible MSC1210
01: #include <msc1210.h>
02: #include "ser_msc1210.h"
03: #include <stdio.h>
04: #include <stdlib.h>
05:
06: #define MAX_FIB 49
07:
08: // surdefinition du sous-programme putchar
09: void putchar(char c) {
10: ser_putc(c);
11: }
12:
13: unsigned long iterative_fibonacci(unsigned long f) {
14:
15: unsigned long nombrePrecedent = 0, nombreCourant = 1, fibonacci = 0;
16: int i;
17:
18: if (f > 1 )
19: for (i = 1; i < f; i++) {
20: fibonacci = nombrePrecedent + nombreCourant;
21: nombrePrecedent = nombreCourant;
22: nombreCourant = fibonacci;
23: }
24: else
25: fibonacci = f;
26:
27: return fibonacci;
28: }
29:
30: void main(void) {
31:
32: unsigned char s[3] = {'\0','\0','\0'};
33: int n, i;
34:
35: // Appuyer sur <Entree> pour ajuster automatiquement
36: // le debit de la liaison
37: autobaud();
38: EA=1;
39:
40: do {
41: printf("Saisir le nombre de calculs de Fibonacci :\r\n");
42: ser_gets_echo(s, 2);
43: n = atoi(s);
44: if (n >= MAX_FIB)
45: printf("\nFibonacci(%d) depasse la capacite d'un mot de 32 bits\r\n", n);
46: } while (n >= MAX_FIB);
47:
48: printf("\r\n\n");
49: for (i = 0; i < n; i++)
50: printf("Fibonacci (%d) = %lu\r\n", i, iterative_fibonacci(i));
51:
52: while(1);
53: }
On retrouve aussi des résultats identiques aux précédents avec le programme sdcc_fibonacci_iterative.c.
MSC1210 Ver:000305F10 >M0000 ok >M8000 ok >E >T > >Saisir le nombre de calculs de Fibonacci : 11 Fibonacci (0) = 0 Fibonacci (1) = 1 Fibonacci (2) = 1 Fibonacci (3) = 2 Fibonacci (4) = 3 Fibonacci (5) = 5 Fibonacci (6) = 8 Fibonacci (7) = 13 Fibonacci (8) = 21 Fibonacci (9) = 34 Fibonacci (10) = 55
Exemple 7, « Utilisation d'un sous-programme dans le calcul des nombres de
Fibonacci » : Dans le programme
principal (main()), à la ligne 35, on trouve l'appel au
sous-programme iterative_fibonacci(i). La variable
i est passée comme paramètre d'entrée lors de l'appel au
sous-programme.
Entre les lignes 6 et 21, on trouve le sous-programme
.
La ligne 6 correspond au prototype du sous-programme : c'est là que l'on
désigne le nom du sous-programme ainsi que les types des paramètres d'entrée
et de sortie. Dans l'exemple, les paramètres échangés sont de type
iterative_fibonacci(i)unsigned long.
Exemple 8, « Utilisation d'un sous-programme dans le calcul des nombres de
Fibonacci sur la cible MSC1210 » : On retrouve les mêmes
éléments que dans le cas précédent. Le sous-programme
est appelé au niveau de la ligne 50. Ce sous-programme est défini entre les
lignes 13 et 28. Les paramètres échangés sont du même type entre les deux
programmes.iterative_fibonacci(i)
Vous êtes ici :