Avant-propos Les sections ou sous-sections marquées d’un astérisque (*) ne font pas partie de la matière du cours IFT1969. Elles sont destinées à définir complètement le langage C (ANSI-C99) et à en préciser les subtilités. Dans ce cours, nous insisterons sur les notions de base du C ainsi que sur les bonnes habitudes de programmation. Et la première bonne habitude de programmation est de construire des programmes portables (cette remarque s'applique à tous les langages de programmation). Un programme est dit portable si on peut le compiler sur toutes les plateformes (Unix, Linux, Windows, Mac) et avec tous les compilateurs (donc, pour le langage C: Turbo C, Borland C++, Visual C/C++, gcc, etc.). Afin d'écrire des programmes portables lors de la réalisation de vos travaux pratiques, il suffit simplement de suivre la syntaxe propre au langage C tel que définie dans ces notes de cours et aussi d'utiliser les fonctions présentées dans ces notes de cours car elles font partie du standard ANSI (C99). Pourquoi cette remarque? Parce que nous utilisons le logiciel Dev-C++ dans ce cours. Comme son nom l’indique, ce logiciel est capable de traiter n’importe quel programme écrit en C++. Toutefois, lors de la correction des travaux pratiques, nous utilisons un autre logiciel (gcc) qui ne traite que les programmes écrits en C. Il faut donc veiller à ne pas utiliser les extensions du langage C++ dans vos travaux pratiques (le langage C++ est construit à partir du langage C). 1. Introduction 1.1 Le logiciel Dev-C++ Ce logiciel est un environnement de travail permettant d’écrire des programmes en C ou C++, de les compiler et de les exécuter. Il est constitué (principalement) des programmes suivants: - un éditeur de texte un préprocesseur un compilateur un éditeur de liens un chargeur d’exécutable Le préprocesseur, le compilateur et l’éditeur de liens sont invoqués automatiquement avec la commande « compile ». Le chargeur d’exécutable est invoqué avec la commande « run ». Voici le rôle de chacun de ses programmes: - le préprocesseur est responsable d'analyser les directives (tout ce qui commence par le caractère #) et de les exécuter (essentiellement des opérations d'édition de texte: copie de texte, remplacement de certains mots, etc.) - le compilateur est responsable de la traduction de votre programme C en assembleur (voir la section suivante) - l'éditeur de liens est responsable de résoudre les liens vers les fonctions appartenant à des librairies externes (soit la librairie du langage C, ou encore d'autres librairies disponibles sur la plateforme utilisée) - le chargeur d’exécutable est responsable du chargement en mémoire centrale et de l’exécution de votre programme 1.2 Le compilateur C Un ordinateur ne sait pas exécuter un programme écrit en C (ni d'ailleurs en C++, en Java, en Fortran, ou n'importe quel langage dit de haut niveau): le seul langage qu'il «connaisse» est un langage de bas niveau appelé assembleur. L'assembleur (qui varie selon le type de processeur utilisé) est un langage très simple qui permet d'écrire des instructions comme: transférer le contenu de telle adresse mémoire dans un registre, additionner le contenu de deux registres, etc. Le rôle d'un compilateur est de traduire le code écrit dans un langage de haut niveau (dans notre cas, le C) en assembleur. Le compilateur est donc un programme de traduction, mais aussi d'analyse du code. Voici les principales phases effectuées lors d'une compilation: - 1.3 l'analyse lexicale permet de valider le vocabulaire utilisée dans le programme l’analyse syntaxique permet de vérifier si le code correspond bien à la grammaire du langage l’analyse sémantique permet de valider l’utilisation des variables et des fonctions la génération du code intermédiaire permet au compilateur une préparation pour les différentes phases d’optimisation les phases d’optimisation permettent de réduire le code grâce à différentes techniques finalement, la génération du code intermédiaire en assembleur permet de produire un fichier exécutable (extension de fichier « .exe » sur Windows, « .out » sur Linux, etc.) Structure générale d’un programme en C Les directives #include Les directives #define (si nécessaire) Les déclarations globales (si nécessaire) Les fonctions (déclarations et définitions si nécessaire) La fonction principale main() En C, une fonction se compose d'un en-tête et d'un bloc. Un bloc est composé de déclarations, d'instructions ou d'autres blocs. On ne peut pas définir une fonction dans un bloc. Cours IFT 1969 Page 2 de 5 1.4 Exemples Les deux exemples ci-dessous seront expliqués en cours. Remarque: Pour les étudiant(e)s qui n’ont aucune notion de programmation, ne paniquez pas si les concepts présentés vous semblent embrouillés. Tous les éléments seront repris de manière détaillée dans les prochains chapitres. Le but étant simplement de vous permettre de compiler et d’exécuter un petit programme dans l’environnement Dev-C++. 1.4.1 Exemple minimal #include <stdio.h> int main() { printf("Bonjour maître\n"); getchar(); return 0; } Remarque: L’appel de fonction getchar() a simplement pour but de laisser la fenêtre d’affichage des résultats sur l’écran. En effet, Dev-C++ fait disparaître cette fenêtre dès que le programme se termine : en exigeant une lecture, le programme doit attendre que l’utilisateur appuie sur la touche « Entrée » avant de terminer. 1.4.2 Exemple un peu plus complet #include <stdio.h> #define PI 3.14159265 float AireCercle (float r) { return PI * r * r; } Cours IFT 1969 Page 3 de 5 int main() { char rep; do { float rayon; printf("Entrez le rayon du cercle: "); scanf("%f", &rayon); printf("Un cercle de rayon %.2f a %.2f de surface\n", rayon, AireCercle(rayon)); printf("Voulez-vous calculer une autre surface" " (o/n)? "); scanf(" %c", &rep); } while (rep == 'o'); return 0; } 1.5 Les commentaires Les commentaires sont destinés à expliquer au lecteur du code la signification des constantes et variables utilisées dans le programme, ainsi que le rôle de chacune des fonctions composant le programme. En C, les symboles /* et */ sont des délimiteurs de commentaires (tout ce qui se situe entre ces délimiteurs est ignoré par le compilateur). Les commentaires ne peuvent pas être imbriqués. Remarque: En C++, le symbole // débute un commentaire qui se termine à la fin de ligne. Son utilisation est permise dans le cadre de ce cours puisque la norme ANSI-C99 le permet. Remarque: Dans le cadre de ce cours, nous n’exigeons pas de commenter les instructions exécutables puisque nous utilisons des algorithmes simples. Toutefois, si vous souhaitez le faire, éviter les commentaires inutiles comme: /* boucle */ for (i = 0; i < 20; i++) le lecteur du code se rend bien compte que l’instruction for est une boucle! Il faut plutôt dire ce que fait ladite boucle, par exemple: /* calcul du sinus avec la série de Taylor */ for (i = 0; i < 20; i++) Voici l’exemple précédent (1.4.2) avec des commentaires: Cours IFT 1969 Page 4 de 5 Exemple 1.4.2 avec des commentaires #include <stdio.h> #define PI 3.14159265 /* constante célèbre */ /* Calcule l'aire d'un cercle à partir du rayon spécifié r. */ float AireCercle (float r) { return PI * r * r; } /* Auteur: Yves Claude Petit programme didactique qui calcule des aires de cercles tant que l'utilisateur spécifie un nouveau rayon. */ int main() { char rep;/* réponse de l'utilisateur pour un autre calcul */ do { float rayon; /* rayon spécifié par l'utilisateur */ printf("Entrez le rayon du cercle: "); scanf("%f", &rayon); printf("Un cercle de rayon %.2f a une surface de %.2f\n", rayon, AireCercle(rayon)); printf("Voulez-vous calculer une autre surface (o/n)? "); scanf(" %c", &rep); } while (rep == 'o'); return 0; } Cours IFT 1969 Page 5 de 5