Dans cette série d'articles, nous présentons le langage C. Il ne s'agit pas de réécrire les ouvrages de référence donnés en annexe, mais de donner, au travers du C, une méthode de programmation basée sur la notion d'interface.
Au fur et à mesure de notre progression, nous décrirons les éléments indispensables du langage et conduirons le lecteur à consulter les ouvrages de références. Le but poursuivi est clairement de parvenir à construire des programmes de manière segmentée.
Dans cette première partie, nous n'échapperons pas au traditionnel "hello word" ! Nous décrions aussi la manière d'utiliser les outils propres au C, comme le compilateur et le lieur. Cette présentation est basée sur les outils GNU comme gcc, ld et ar et le débogueur gdb. Elle peut être transposée dans d'autres environnements comme les plates-formes Microsoft, bien que les outils y soient souvent complètement intégrés, confisquant du même coup la souplesse, la puissance et la liberté à l'utilisateur.
Introduction
Ce langage fut créé en 1972 dans les laboratoires Bell AT&R par Dennis Ritchie. C'est un langage algorithmique et impératif appartenant à la même famille que Pascal, PL/1.
C'est un langage primitif, à la frontière de l'assembleur et des langages évolués. Il est facile à compiler, facile à porter vers d'autres machines. En effet, il a été conçu de manière à ce que le compilateur soit simple et rapide.
Dans les premiers temps, Unix était écrit en assembleur (langage machine) et en B, un ancêtre du C, non typé. Le portage vers d'autres ordinateurs posait des problèmes. L'idée fut de réécrire le plus de code possible de Unix en C. Seules certaines parties demeurent écrites en assembleur. Unix étant très utilisé dans les Universités, le langage C devint vite populaire et très utilisé. On le trouve sur quasiment toutes les architectures, du processeur spécialisé pour le traitement du signal (DSP), en passant par les micro-ordinateurs, jusqu'aux super calculateurs.
Un programme C est portable d'une architecture à l'autre. Cependant, le portage peut poser des problèmes, notamment en ce qui concerne la taille des mots. Ainsi, sur un 8086, un entier est codé sur 16 bits, alors que sur un 386, il est codé sur 32 bits.
Le C est utilisé pour programmer des applications aussi diverses que les systèmes d'exploitation, les gestionnaires de base de données, les interfaces graphiques.
Le langage C est normalisé par l'American National Standard Institut (ANSI) depuis 1982. Avant cette normalisation, le langage C était "normalisé" par une annexe du livre de Brian Kernignan et Dennis Ritchie, connue sous le nom de K&R.
Le langage C a continué d'évoluer en se dotant d'un moteur à Objet pour donner naissance au langage C++, conçu par Bjarn Stroustrup. Le langage C++ offre de réelles innovations, mais les compilateurs C++ restent lents, et les puristes préfèrent continuer à développer en C.
Au cours de ces articles, nous montrerons comment programmer en C en utilisant une "approche orientée objets".
Hello Word!
Nous supposons que nous travaillons sur une station Unix, de préférence Linux. Le compilateur C a été correctement installé, ainsi que les bibliothèques de développement.
Nous recommandons de travailler avec l'éditeur de texte emacs ou jed, qui possèdent tous les deux un mode C qui reconnaît la syntaxe C. Emacs va plus loin puisqu'il permet de compiler automatiquement les programmes, de les déboguer : il propose un véritable environnement de programmation C.
Plaçons-nous dans un répertoire de travail. Tapons le fichier suivant, nommé hello.c :
#include <stdio.h>
void main (void) {
printf ("hello word !\n");
}
Emacs permet d'indenter correctement les programmes. Pour cela, tapez la touche TAB au début sur une ligne (ou au début d'une ligne). Au lieu de placer une tabulation, emacs indente la ligne (indenter signifie placer des blancs au début des lignes pour montrer la hiérarchie des blocs du programme). Seule la première pression sur TAB à un effet, les autres sont ignorées. Donc, lorsque l'on tape ENTER pour retourner au début de la ligne, on tape aussi TAB pour indenter la ligne.
La mise en forme de emacs est conforme à l'usage. Cela ne veut pas dire que le programme ne sera pas reconnu si l'on opte pour une autre mise en forme. En fait, seules les lignes commençant par # doivent être suivies d'un saut à la ligne. Les autres peuvent être écrites comme l'on souhaite, comme :
#include <stdio.h>
void main(void){printf("hello word !\n");}
Le programme est constitué de mots séparés par des séparateurs. Le séparateur le plus important est le blanc. En C, un blanc est un espace, une tabulation, un saut à la ligne, ou toute autre combinaison de blancs. Les autres séparateurs sont < > ( ) " { } [ ] ; , et les opérateurs arithmétiques. Le lecteur se référera aux ouvrages cités en annexe pour lire la grammaire complète du langage C.
On reconnaît donc les mots #include, stdio.h, void, main et printf. Comme dans la plupart des autres langages, les chaînes de caractères constantes sont entourées de guillemets.
Attention, le C fait la différence entre les minuscules et les majuscules.
La première ligne indique au compilateur d'utiliser la bibliothèque des entrées / sorties standard. Nous verrons plus tard ce que cela implique exactement.
La ligne suivante définit une fonction appelée main. Cette fonction ne retourne rien (premier void) et n'a pas de paramètres (void entre parenthèses). La fonction main est un peu particulière : dans tout programme C, quel que soit sa taille, il n'y a qu'une seule fonction appelée main, et c'est le point d'entrée du programme.
Ce qui est placé entre les accolades constitue le corps de la fonction : ce sont des instructions séparées par des points virgules. Ce corps ne comporte qu'une seule instruction. C'est un appel à la fonction printf, avec comme argument, la chaîne de caractères constante Hello word !\n La fonction printf est chargée de l'affichage à l'écran des arguments. Notez que le caractère \n dans la chaîne à une signification spéciale : il sera remplacé par un saut de ligne lorsqu'il sera affiché.
Compilation
Nous avons donc écrit notre premier programme C. Il nous reste à l'exécuter.
Pour l'instant, notre programme C n'est qu'un fichier texte placé sur le disque. Le microprocesseur ne sait sûrement pas quoi en faire. Il nous faut traduire ce programme C dans le langage du processeur.
Cette traduction est faite par le compilateur C qui transforme du C en langage machine. On aurait pu appeler le compilateur "traducteur"; on appelle compilateur de langage un programme qui transforme un langage en un autre, le langage produit étant sémantiquement moins riche que le premier. En général, le langage en entrée du compilateur est appelé langage source, ou source, le langage produit est appelé code objet (attention, ici, objet ne fait pas référence à la programmation objet).
Pour compiler notre programme hello.c, nous tapons sur la ligne de commande :
$ gcc -o hello hello.c
gcc est le nom du compilateur C du GNU. L'option -o hello force le compilateur à fabriquer un exécutable dont le nom sera hello. Cette commande fabrique donc un fichier exécutable hello. C'est un nouveau programme dans notre système. Maintenant, tapons :
$ ./hello
hello word !
$
Miracle, ça marche !
Fonction, bloc d'instructions
Le programme précédent nous a montré comment définir une fonction. Allons un peu plus loin.
Une fonction permet de donner un nom et des paramètres à un bloc de code.
Un bloc de code est délimité par des accolades. Le contenu du bloc de code est, par convention, indenté. Structurellement, un bloc de code contient deux parties : la partie des déclarations, et la partie des instructions :
{
déclaration1;
déclaration2;
...
déclarationm;
instruction1;
instruction2;
...
instructionn;
}
Un bloc de code peut ne contenir aucune déclaration ni aucune instruction. Ainsi, le plus petit bloc est { }.
La partie des déclarations déclare ou définit des variables locales qui ne sont accessibles qu'aux déclarations et aux instructions situées sous elle, dans le même bloc ou les blocs inclus.
Les déclarations et les instructions sont exécutées de la gauche vers la droite et du haut vers le bas.
La définition d'une fonction comprend deux parties : le prototype et le corps. Le prototype contient le type de la valeur de retour de la fonction, le nom de la fonction, la liste des ses paramètres. La description des types de base et du nom des fonctions est donnée plus bas, dans la section " Variables ".
La liste des paramètres est formée des couples type-nom des paramètres, séparés par des virgules, ou rien, ou le mot clef void. (qui signifie "sans type").
Le corps de la fonction est un bloc. Une fonction ne peut pas être définie dans un bloc (à la différence du langage Pascal). Ainsi, la définition d'une fonction s'écrit :
type_retour nom_fonction (liste_paramètres) {
déclaration1;
déclaration2;
...
déclarationm;
instruction1;
instruction2;
...
instructionn;
}
Si on omet le corps de la fonction, on obtient la déclaration de la fonction. Ainsi :
int fonction (int n)
déclare la fonction fonction, retournant un entier et attendant un entier. Nous étudierons plus tard l'utilité des déclarations de fonctions.
En C, les fonctions ne sont pas des objets de première classe, comme en Scheme (le lecteur se réfèrera aux articles sur Scheme dans le même magazine). Cela signifie qu'il ne gère pas tout à fait de la même manière la déclaration d'une variable et la déclaration d'une fonction. Nous verrons plus tard et plus précisément ces différences.
Variables
Une variable est représentée en C par un nom. Un nom de variable peut contenir toutes les lettres de l'alphabet, les chiffres, la lettre _. Ainsi, toto, grand_toto, toto1 sont des noms de variables corrects. 1toto, grand-toto sont des noms incorrects.
Le langage C comporte un certain nombre de types de données de base. Les principaux sont :
Ainsi:
char toto;
int titi;
déclare la variable toto comme de type caractère et titi de type entier. Le type de la variable va servir à déterminer la quantité de mémoire réservée dans la machine pour stocker le contenu de la variable et à aider le compilateur à détecter les erreurs de type.
Le langage C permet au programmeur de construire ses propres types de données, comme nous le décrirons ultérieurement.
Affectation
Pour donner une valeur à une variable, C définit l'opérateur = qui s'utilise comme suit :
int entier;
entier = 123;
L'expression à droite du signe = est évaluée et son résultat est placé dans la variable. Attention, ce n'est pas une équation, mais bien une affectation. Ainsi, il est possible d'écrire :
int n;
n = 2;
n = n + 1;
A la fin, la variable n vaut 3. L'expression n = n + 1 n'est pas une équation.
Il est aussi possible de déclarer des variables et de les initialiser en même temps, comme dans :
int entier = 123;
Les caractères s'écrivent entre quotes. Ainsi, 'a' représente la lettre a, '1' représente la lettre 1. On peut alors écrire :
char un_car = 'A';
Affichage
Nous avons vu que la fonction printf sert à l'affichage à l'écran.
Elle attend comme premier paramètre une chaîne de format. Tous les caractères de cette chaîne sont affichés tels quels. Dans cette chaîne, les séquences de caractères %c, %d, %f sont remplacés par la valeur des arguments correspondant, lus respectivement comme un caractère, un entier et un réel. La séquence de caractère \n est remplacée par un saut de ligne et la séquence \t est remplacée par une tabulation.
Nous avons :
printf ("le caractère %c et l'entier %d\n", 'a', 123);
- le caractère a et l'entier 123
printf ("%c\t%c\n%d\t%d\n", 'z', 'a', 456, 123);
- z a
- 456 123
Attention, C ne vérifie pas le nombre et la correspondance des types entre les séquences % et les arguments.
Exemple
Dans cet exemple final, nous allons mettre en pratique nos connaissances :
#include <stdio.h>
void main (void) {
int x;
x = 10;
printf ("x vaut %d\n", x);
}
Nous utilisons toujours la bibliothèque d'entrées / sorties standard.
Puis nous définissons la fonction main, ne retournant rien et sans paramètre. Son corps déclare un entier x. La première instruction du corps affecte la valeur 10 à la variable x. Puis elle appelle printf, avec une chaîne de format contenant un %d qui sera remplacé à l'affichage par la valeur de x, c'est à dire 10.
Ce qu'il faut retenir
Dans cet article, nous avons vu les rudiments du langage C. Nous avons commencé à décrire la chaîne de compilation associée à ce langage, les blocs d'instruction et les fonctions, les variables et leur affectation ainsi que les types primitifs.
Guilhem de Wailly,
directeur de la société Erian Concept :
support, formation, configuration, administration, développement Linux.
http : // www.erian-concept.com