Un programme simple se compose de plusieurs parties : •les directives de précompilation •les déclaration des variables globales et des fonctions •une ou plusieurs fonctions dont l’une s’appelle obligatoirementmain(), celle-ci constitue le programme principal et comporte 2 parties : ⋆la déclaration de toutes les variables ⋆des instructions Les commentaires débutent par/*et finissent par*/, ils peuvent s’étendre sur plu-sieurs lignes.
1.1 Les directives de précompilation Elles commencent toutes par un#. directive signification #include<stdio.h>inclut le fichier d’en-têtesstdio.h, qui permet d’utiliser les fonctions d’entrée et sortie telles queprintf()ouscanf() #include<math.h>permet d’utiliser les fonctions mathématiques #include<stdlib.h>permet d’utiliser certaines fonctions utilitaires telles que la génération de nombre aléatoire, l’allocation dynamique de mémoire, ainsi que certains types de variables #definePI 3.14159définit la constantePI #undefPIà partir de cet endroit, la constantePIn’est plus définie #ifdefPI #ienlssteructions 1 ...insssilnion,lestanacontePtIno,einfiélelipmocrustinesnsioctrucietsntdo2s instructions 2 ...1, s #endif Parmi ces directives, une est très souvent nécessaire pour le bon fonctionnement d’un programme :#include<stdio.h>. En effet, sans elle, on ne peut pas utiliser les fonc-tions utiles pour l’affichage à l’écran :printf()et la lecture des données au clavier :
6
Chapitre1.Lesbases
scanf(). Nous verrons le fonctionnement de ces fonctions plus tard. Pour inclure un fichier situé dans le répertoire courant, l’instruction est légèrement différente :#include"monfichier.h". On note les guillemets au lieu des<...>. Ces derniers indiquent qu’il faut aller chercher ledit fichiers dans les répertoires connus du compilateur (/usr/includepar exemple), alors que les guillemets indiquent le répertoire courant.
1.2 La fonctionmain() C’est la fonction principale de votre programme. C’est-à-dire que si vous avez plu-sieurs fonctions dans votre programme, c’est celle-ci qui sera exécutée en premier par l’ordinateur.
Elle commence par une accolade ouvrante{et se termine par une accolade fermante }l’intérieur, chaque instruction se termine par un point-virgule. Toute variable. À doit être déclarée. Le mot-clévoidindique que le programme ne nécessite pas d’arguments lors de son exécution. Si un argument est donné, il sera ignoré. Le mot-cléintsignifie que la valeur de retour du programme est un entier. Habituel-lement, cette valeur vaut 0 en cas de succès ou 1 en cas d’échec (on trouve aussi des valeurs>1pour différencier les différentes erreurs possibles). La valeur de retour est utile lorsque le programme est appelé par un autre programme : ce n’est pas une valeur affichée à l’écran. On peut l’obtenir depuis le shell par la commandeecho $? juste après l’exécution du programme. Exemple de programme simple :
Note: la chaîne de caractères\nl’écran un retour à la ligne. Il est importantaffiche à de prendre l’habitude de la mettre systématiquement. En effet, le C n’affiche pas forcément le résultat d’unprintf()au moment où cette commande est évaluée, sauf s’il y a un\nà la fin. Une conséquence de ce comportement est que si le programme
2.LacompilationsousUnix
7
plante avant d’avoir affiché ladite chaîne de caractère, il est difficile de savoir à quel moment ce dernier a planté si on utiliseprintf()pour déboguer.
1.3 Donner des arguments àmain() Lorsqu’un programme est lancé depuis le shell avec des arguments, ce dernier trans-met au programme les informations suivantes : •le nombre d’arguments •un tableau de chaîne de caractères contenant tous les arguments Dans les 2 variables, le nom de l’exécutable est compris, ainsi, si on exécute ./ mon_programme a 5 toto le nombre d’arguments est 4, et le tableau d’arguments contient : numéro valeur 0 mon_programme 1 a 2 5 3 toto Par convention, l’argument qui détient le nombre d’arguments s’appelleargcet est un entier, et le tableau contenant les chaînes de caractères s’appelleargvet est un tableau de chaînes de caractères. Le prototype de la fonctionmaindevient donc :
intmain (intargc ,char {** argv ) inti; printf );("Le programme a reçu %d arguments :\n" , argc for { ++) i ;(i = 0; i < argc printf [i ]); %s\n", argv(" -> } }
AITNOTTNE:Si on donne des chiffres comme arguments, ils seront lus comme des chaînes de caractères. Il faut penser à les convertir en entiers ou en réels. Nous reviendrons sur la notationchar**argvau moment du chapitre sur les poin-teurs.
2 La compilation sous Unix Une fois le programme écrit, on ne peut pas l’exécuter directement. Pour que l’ordi-nateur comprenne ce que l’on veut lui faire faire, il faut traduire le programme en langage machine. Cette opération s’appelle lacompilation. On compile le programme par la commandecc prog.c, où prog.c est le nom du pro-gramme. La compilation crée un fichier exécutable :a.out. On peut vouloir lui donner un nom plus explicite, et pour cela, à la compilation, on compile avec la commande cc -o prog prog.cqui va appeler le programme exécutableprogau lieu dea.out. On démarre alors le programme avec la commande./prog.
Chapitre 2
Variables et constantes
1 Les constantes Constantes entières1,2,3, ... Constantes flottantes3.14159, ... Constantes caractères’a’,’A’, ... Constantes chaînes de caractères"Bonjour" Pas de constantes logiquesPour faire des tests, on utilise un entier. 0 est équi-valent à faux et tout ce qui est non nul est vrai.
2 Les variables
2.1 Noms des variables Le C fait la différence entres les MAJUSCULES et les minuscules. Donc pour éviter les confusions, on écrit les noms des variables en minuscule et on réserve les ma-juscules pour les constantes symboliques définies par un#define. Les nomsdoivent commencer par unelettreet ne conteniraucun blanc. Le seul caractère spécial admis est le soulignement (_). Il existe un certain nombre de noms réservés : •break•else•static •case•float•struct •char•for•switch •const•if•union •continue•inline•unsigned •default•long•void •do•return•while •double•short
dont on ne doit pas se servir pour nommer les variables. De plus, on ne doit pas utiliser les noms des fonctions pour des variables.
10
Chapitre2.Variablesetconstantes
2.2 Déclaration des variables Pour déclarer une variable, on fait précéder son nom par son type. Il existe 7 types de variables dont les significations dépendent du processeur de la machine. Le tableau ci-dessous les donne pour un processeur 32 bits. type signification val. min val. max charouint8_tcaractère codé sur 1 octet (8 bits)−2727−1 shortouint16_tentier court codé sur 2 octets−215215−1 intouint32_tentier codé sur 4 octets−231231−1 longouint64_tentier long codé sur 8 octets−263263−1 long longentier très long codé sur 8 octets−263263−1 floatréel codé sur 4 octets∼ −1038∼1038 doubleréel double précision codé sur 8 octets∼ −10308∼10308 Sur un processeur 64 bits, les entiers courts, standards, longs et très longs sont codés respectivement sur 2, 4, 8 et 16 octets. Les réels sont codés sur 8 octets et les double précision sur 16 octets. Pour s’assurer qu’un même code se comporte de la même façon sur des machines diffé-rentes, on utilise de préférence les appellationsint16_t,int32_touint64_tàshort,int etlong. En effet, ces appellations ont le mérite d’être explicites et invariantes d’un processeur à un autre. Pour pouvoir utiliser ces types, il faut inclure le fichier d’en-têtes<stdlib.h>en début de programe. On peut faire précéder chaque type par le préfixeunsigned, ce qui force les variables à prendre des valeurs uniquement positives. Exemples de déclarations :
déclaration signification inta; aest entier intz = 4; zest entier et vaut 4 unsigned intx; xest un entier positif (non signé) float zxzx, zy;etzysont de type réel floatzx = 15.15; zxest de type réel et vaut 15.15 doublez; zest un réel en double précision charzz; zzest une variable caractère charzz = ’a’; zzvaut’a’ Il n’y a pas de type pour les nombres complexes. La notation flottante pour un réel Pour les réels, il est parfois impossible (et inutile) de noter tous les chiffres d’un nombre. On utilise alors la notation flottante comme en mathématiques. Ainsi,3 106 se notera :
x = 3e6
3.Lesopérateurs
3 Les opérateurs
11
Le premier opérateur à connaître est l’affectation, notée "=". Exemple :a = b;Il sert à mettre dans la variable degauchela valeur de ce qui est à droite. Le membre de droite est d’abord évalué, et ensuite, on affecte cette valeur à la variable de gauche. Ainsi l’instructioni = i+1;a un sens. Pour les opérations dites naturelles, on utilise les opérateurs+,-,*,/,%. %est l’opération modulo :5 % 2est le reste de la division entière de 5 par 2.5 % 2est donc égal à1. Le résultat d’une opération entre types différents se fait dans le type capable de sto-cker le plus grand nombre. Les types sont classés ainsi :
char<short<int<long<float<double Par ailleurs, l’opération 1;’a’ +a un sens, elle a pour résultat le caractère suivant à a(c’est-à-direb). En C, il existe un grand nombre d’opérateurs spécifiques, qu’il faut utiliser prudem-ment sous peine d’erreurs. ++incrémente la variable d’une unité. --décrémente la variable d’une unité. Ces 2 opérateurs ne s’utilisent pas avec des réels. Exemples d’utilisation :
i ++; /* équivaut à i=i+1 */ i - -; /* équivaut à i=i-1 */
Leur utilisation devient délicate quand on les utilise avec d’autres opérateurs. Exemple :
inti, j; i = 1; j=i++;/*effectued’abordj=ietensuitei=i+1 on a alors j=1 et i=2 */ i = 1; j=++i;/*effectued’abordi=i+1etensuitej=i on a alors j=2 et i=2 */ i=j+++1;/*équivalentài=(j++)+1 effectued’abordi=j+1etensuitej=j+1 on a alors j=3 et i=3 */
Quand l’opérateur++est placé avant une variable, l’incrémentation est effectuée en premier. L’incrémentation est faite en dernier quand++est placé aprés la variable. Le comportement est similaire pour--.