Hello Word! - Guilhem de Wailly

publicité
Le langage C
Première partie
Par :
Guilhem de Wailly ([email protected])
Résumé
Hello Word!
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.
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.
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 poursuivit est
clairement de parvenir a construire des programmes de manière
segmentée.
Dans cet 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 plateformes Microsoft, bien que les
outils y soit 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çut 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és 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 diverse
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
compilateur C++ restent lents, et les puristes préfèrent continuer
à développer en C.
Au cours de ces articles, nous montrerons comme programmer
en C en utilisant une `` approche orientée objets ''.
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
automatique 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, taper 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
peut particulière : dans tout programme C, quelque 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 st
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 a 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 !
$
La liste des paramètres est formée des couple 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 a
fait de la même manière la déclaration d'une variable et la
déclaration d'une fonction. Nous verrons plus tard plus
précisément ces différences.
Variables
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 ''.
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.
La langage C comporte un certain nombre de types de données
de base. Les principaux sont :

char :
caractère

int :
entier signé

unsigned :
entier non signé

float :
réel court sur 32 bits

double :
réel long sur 64 bits
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éserver 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;
L'auteur
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 rempalcé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ètres. 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
Références
Langage C - norme ANSI
Ph. DRIX
Masson
Programmer en C++
S.C. DEWHURST et K.T. STARK
Masson
Le Langage C
B.W. KERNIGHAN et D.M. RITCHIE
Masson
Téléchargement