Upload
anass-el-mrini
View
218
Download
0
Embed Size (px)
Citation preview
8/6/2019 programmation_C
1/123
Avant-propos 1
Avant-proposNous vous proposons, par ce livre, d'apprendre la programmation en langage C. Dans ce
livre, nous supposerons que le lecteur a des notions de base en programmation,
algorithmique et structures de donnes; si vous n'en avez pas, ou si vous voulez rviser des
notions pendant l'apprentissage du C, vous pouvez consulter les wikilivres associs:Programmation, Algorithmique et Structures de donnes.
Le langage C permet d'apprhender des principes informatiques de bas niveau, lis
l'architecture d'un ordinateur, comme la gestion de la mmoire. Si la connaissance de ces
principes peut aider comprendre certains cts du langage C, ils ne sont cependant pas
ncessaires pour lire ce wikilivre, les concepts tant expliqus chaque fois que
ncessaire.
Ce livre, en constante volution, est issu d'un projet collaboratif. Si vous trouvez des
erreurs, vous pouvez le corriger directement l'aide des liens Modifier sur chaque
page. Vous pouvez poser des questions et apporter vos remarques en laissant un nouveaumessage [1] sur la page de discussion de ce livre. Toute question ou participation est la
bienvenue !
Bonne lecture !
Rfrences[1] http://fr.wikibooks.org/ w/wiki.phtml?title=Discuter:Programmation_C&action=edit&
amp;section=new
SommaireVoici une description rapide des diffrents chapitres qui constituent ce livre:
Introduction
Le C a une longue histoire... Cr il y a plus de 30 ans, il a beaucoup volu depuis.
Nous expliquerons ici son histoire, dcrirons ses principales caractristiques et
domaines d'utilisation, et fournirons des raisons de l'apprendre (ou de ne pas
l'apprendre).
Bases du langage
Dans cette partie, nous tudierons les concepts de base du langage C, sa syntaxe ainsique la manire dont un programme est structur.
Types de base
Ensuite, nous prsenterons les diffrents types de base que fournit le langage C. Ces
types tant pour l'essentiel des nombres (entiers, rels et complexes), ce chapitre
traitera aussi de l'arithmtique associe ces types. Les types caractres, qui sont la
base de nombreux traitements, et ont un rle particulier dans ce langage, seront aussi
dfinis.
Classe de stockage
Le C permet de construire des constantes, par le biais de classes de stockages.Celles-ci permettent de dfinir plus gnralement des types drivs des types de base
http://fr.wikibooks.org/w/wiki.phtml?title=Discuter:Programmation_C&action=edit§ion=newhttp://fr.wikibooks.org/w/wiki.phtml?title=Discuter:Programmation_C&action=edit§ion=newhttp://fr.wikibooks.org/w/wiki.phtml?title=Discuter:Programmation_C&action=edit§ion=newhttp://fr.wikibooks.org/w/index.php?title=Structures_de_donn%C3%A9eshttp://fr.wikibooks.org/w/index.php?title=Programmation_Algorithmiquehttp://fr.wikibooks.org/w/index.php?title=Programmation8/6/2019 programmation_C
2/123
Sommaire 2
et seront tudis dans ce chapitre.
Oprateurs
Nous tudierons ensuite les oprateurs permettant de travailler sur les types de base,
ainsi que les rgles gnrales qui structurent les expressions en C.
Structures de contrle - tests
La notion d'expression dfinie, nous aborderons les moyens de contrler le fluxd'excution d'un programme. Tout d'abord, les tests de type Si...Alors...Fin Si seront
tudis.
Structures de contrle - itrations
Dans la suite du chapitre prcdent, nous tudierons les structure d'itrations, ou
boucles, de typePour, Tant que ou drivs.
Fonctions et procdures
Comment le C prend en charge les fonctions et procdures.
Tableaux
Comment le C gre les tables de donnes.
Pointeurs
Les pointeurs sont une spcificit du C, souvent mal comprise. Ce chapitre dfinira et
montrera comment bien utiliser les pointeurs, ainsi que les erreurs viter dans leur
manipulation.
Types avancs - structures, unions, numrations
Explications sur les types avancs du C.
Prprocesseur
Le prprocesseur est un langage au-dessus du C, que l'utilisateur rencontre pour lapremire fois dans l'utilisation des directives d'inclusion d'en-ttes de la bibliothque
standard. Cependant, il est capable de bien plus, et fournit des outils comme les
macros ou l'inclusion conditionnnelle, qui sont l'objet de ce chapitre.
Bibliothque standard
Cette partie a pour but de familiariser le lecteur avec la bibliothque standard du
C. Celle-ci propose un ensemble de fonctions, mais aussi de types ou de variables
permettant d'effectuer des oprations spcifiques, comme les traitements de fichiers,
les calculs mathmatiques, ou la gestion des chanes des caractres.
Chanes de caractresCe chapitre traite de toutes les fonctions permettant d'effectuer des traitements sur
les chanes de caractres : concatnation, copie, recherche de caractres, etc.
Entres/sorties
Ce chapitre traite des interactions avec l'utilisateur.
Erreurs
La bibliothque standard utilise un mcanisme unique pour la gestion d'erreur, qui
permet un programme de dterminer prcisment la cause de l'chec d'une fonction
de la bibliothque standard.
Mathmatiques
Ce chapitre dtaille les fonctions mathmatiques fournies par la bibliothque standard.
8/6/2019 programmation_C
3/123
Sommaire 3
Gestion de la mmoire
La bibliothque standard fournit un moyen d'allouer et de librer dynamiquement de la
mmoire au cours de l'excution du programme. Cette fonctionnalit est surtout
utilise pour rsoudre des problmes dont le volume des donnes traiter varie d'une
excution l'autre.
Gestion des signauxUn signal est une interruption logicielle reue par un processus. Ces interruptions
fournissent un moyen de communication entre le systme et un programme, pour
informer le programme de situations d'erreur (utilisation d'une zone de mmoire
invalide, par exemple), ou informer un processus d'vnements asynchrones (fin d'une
opration d'entre/sortie). Le C permet d'envoyer et de traiter la rception de ces
signaux.
Conclusion
Introduction
Historique
Naissance
Le langage C a t invent aux Bells Labs en 1972 par Dennis Ritchie pour permettre
l'criture du systme d'exploitation UNIX, alors dvelopp par Ken Thompson et Dennis
Ritchie.
Le systme d'exploitation UNIX, n la fin des annes 1960 - dbut des annes 1970, a tcrit directement en langage assembleur pour les machines auxquelles il tait destin. Si le
langage assembleur permettait d'crire un tel systme, il n'en tait pas moins peu ais
utiliser. Un tel langage est en effet particulier un type de processeur, ce qui fait que tout
le systme devait tre rcrit pour le faire fonctionner sur une nouvelle architecture. Cela
fait que son principal crateur, Ken Thompson, souhaita rapidement utiliser un langage
plus volu pour rcrire UNIX.
Parmi les langages disponibles l'poque, BCPL (pour Basic Combined Programming
Language, qui est une simplification de CPL), cr par Martin Richards en 1966, tait
intressant. Sans entrer dans des descriptions dtailles, BCPL est un langage simple,
procdural, et non typ. Sa simplicit permettait de crer facilement des compilateursBCPL sur les machines de l'poque, o les ressources taient trs limites (le premier
ordinateur utilis par Keith Thompson pour lancer Unix tait un PDP-7, qui disposait d'une
mmoire de 4000 mots de 18 bits, soit moins de 9 Ko). Ken Thompson l'a fait voluer pour
concevoir le langage B, qu'il a implment sur les premires machines UNIX. Cependant,
certaines limitations du langage B ont fait qu'UNIX n'a pu tre rcrit dans ce langage.
partir de 1971, Dennis Ritchie fit voluer B, pour rpondre ces problmes. l'image des
programmeurs qui incrmentent les versions de leurs programmes, Ritchie incrmenta
la lettre B pour appeler le nouveau langage C. Cette volution se stabilisa vers 1973,
anne partir de laquelle UNIX et les utilitaires systmes d'UNIX ont t rcrits avec
succs en C.
http://fr.wikipedia.org/wiki/B_(langage)http://fr.wikipedia.org/wiki/Kenneth_Thompsonhttp://fr.wikipedia.org/wiki/UNIXhttp://fr.wikipedia.org/wiki/Syst%E8%AD%A5_d'exploitationhttp://fr.wikipedia.org/wiki/Dennis_Ritchie8/6/2019 programmation_C
4/123
Introduction 4
Dveloppement
Par la suite en 1978, Brian W. Kernighan documenta trs activement le langage, pour
finalement publier avec Ritchie le livre de rfrence The C Programming Language. On
appelle souvent C K&Rle langage tel que spcifi dans la premire dition de ce livre.
Dans les annes qui suivirent, le langage C fut port sur de nombreuses autres machines.
Ces portages ont souvent t faits, au dbut, partir du compilateur pcc de Steve Johnson,mais par la suite des compilateurs originaux furent dvelopps indpendamment. Durant
ces annes, chaque compilateur C fut crit en suivant les spcifications du K&R, mais
certains ajoutaient des extensions, comme des types de donnes ou des fonctions
supplmentaires, ou interprtaient diffremment certaines parties du livre (qui n'tait pas
forcment trs prcis). cause de cela, il fut de moins en moins facile d'crire des
programmes en C qui puissent fonctionner tels quels sur un grand nombre d'architectures.
Normalisation
Pour rsoudre ce problme, et ajouter au C des possibilits dont le besoin se faisait sentir
(et dj existantes dans certains compilateurs), en 1989, l'organisme national de
normalisation des USA (ANSI) normalisa le C. Le nom exact de cette norme est ANSI
X3.159-1989Programming Language C, mais elle fut (et est toujours) connue sous les
dnominations ANSI C ou C89. Puis l'ANSI soumit cette norme l'Organisation
internationale de normalisation (ou ISO), qui l'accepta telle quelle et la publia l'anne
suivante sous le numro ISO/IEC 9899:1990 (le document tant connu sous le nom ISO
C90, ou C90). Le besoin de normalisation de l'poque tant extrmement pressant,
pratiquement tous les diteurs de compilateurs C de l'poque se sont mis modifier leurs
compilateurs pour supporter la norme (et mme n'ont pas attendu la publication officielle
pour lancer ces modifications), et de fait la quasi totalit des implmentations existant ce
jour comprennent ces normes. L'ISO publia dans les annes qui suivirent deux ensembles
de correctifs, et un amendement pour la gestion des caractres internationaux.
tant donne la grande diversit des implmentations existants au moment de l'laboration
de la norme, et le principe de ngociation qui base les processus de normalisation, la norme
C est un compromis. Son but tait principalement double : d'une part assurer le plus
possible la portabilit du code C, pour simplifier le portage de programmes C d'une
implmentation une autre (ce qui tait souvent un cauchemar raliser), d'autre part
donner une certaine libert aux diteurs pour proposer des extensions spcifiques. Pour ce
faire, la norme a dfini des niveaux de conformit pour les programmes C et les
implmentations, allant du programme strictement conforme, que toute implmentationdoit accepter, et qui fonctionnera exactement de la mme manire, aux programmes
dpendant d'extensions.
On peut noter que le livre de Kernighan et Ritchie a t republi dans une seconde dition,
pour reflter les changements du C89.
Enfin, en 1999, l'organisme ISO proposa une nouvelle version de la norme, qui reprenait
quelques bonnes ides du langage C++ (voir plus bas). Il ajouta aussi le type long long
d'une taille minimale de 64 bits, les types complexes, l'initialisation des structures avec des
champs nomms, parmi les modifications les plus visibles. Le nouveau document, qui au
niveau de l'ISO est celui ayant autorit aujourd'hui, est ISO/IEC 9899:1999, connu sous le
sigle C99. Deux ensembles de correctifs cette version ont t publis jusqu' prsent. Ausens strict, la dnomination ISO C correspond donc actuellement la norme de 1999
http://fr.wikipedia.org/wiki/Organisation_internationale_de_normalisationhttp://fr.wikipedia.org/wiki/Organisation_internationale_de_normalisationhttp://fr.wikipedia.org/wiki/American_National_Standards_Institutehttp://fr.wikipedia.org/wiki/American_National_Standards_Institutehttp://fr.wikipedia.org/wiki/Brian_Kernighan8/6/2019 programmation_C
5/123
Introduction 5
corrige, mais l'usage est tel qu'il est prfrable de toujours prciser de quelle version on
parle (89/90 ou 99), et c'est ce qui sera fait dans cet ouvrage lorsque la distinction sera
ncessaire. Il est noter que, si la norme C90 a t largement adopte par les diteurs de
compilateurs C, trs peu implmentent la version C99. En effet, le besoin des utilisateurs
s'est fait moins pressant, et l'effort ncessaire pour rendre les compilateurs conformes a
rarement t men terme.
L'activit du groupe de travail de la norme C est, depuis, porte plus sur la maintenance
du langage qu' de vritables volutions . La prochaine version, dnomme
officieusement C1Xpour l'instant, n'est pas encore publie et ne sera pas tudie dans ce
livre[1] .
La norme C spcifie la syntaxe du langage ainsi qu'une bibliothque de fonctions simple.
Cette bibliothque est moins fournie que dans d'autres langages, mais cela est d au
domaine d'utilisation trs vari de ce langage. En particulier, pour assurer une portabilit
maximale du langage entre les implmentations embarques, les ordinateurs de type PC et
les supercalculateurs (par exemple), certaines fonctions n'ont pas t acceptes dans la
norme. On peut citer, entre autres, la programmation parallle, les communications entreprocessus, la communication rseau ou les interfaces graphiques...
Cela fait qu'en parallle de cette normalisation du langage C, certaines extensions ont elles
aussi t standardises, voire normalises. Ainsi, par exemple, des fonctions spcifiques
aux systmes UNIX, sur lesquels ce langage est toujours trs populaire, et qui n'ont pas t
intgres dans la norme du langage C, ont servi dfinir une partie de la norme POSIX.
Dans ce livre, nous tudierons surtout le langage C tel que dfini dans les normes ISO
cites ci-dessus. La norme C99 n'tant pas implmente par tous les compilateurs, et
beaucoup de programmes existants tant dvelopps en C90, les diffrences entre les deux
normes seront indiques chaque fois que ncessaire. Toutefois, nous illustrerons certains
chapitres avec des exemples d'extensions courantes qu'un dveloppeur C peut rencontrer,
en particulier concernant les fonctions qui ne sont pas fournies par la norme C elle-mme.
Mais ces exemples d'extensions seront mineurs. D'autres Wikilivres tudient plus en dtails
de telles extensions, vous pouvez les trouver en regardant les livres lists sur la page
Catgorie:C.
Norme et documents de rfrenceLa norme qui dfinit le langage C est labore au niveau international par un groupe de
travail (working group) de l'ISO. Ce groupe de travail fait partie plus prcisment du comit
technique commun l'ISO et la Commission Electrotechnique Internationale, le JointTechnical Commitee 1, qui labore les normes internationales concernant les technologies
de l'information. Il se dcompose en sous-comits, donc le SC22, responsable des langages
informatiques. Le SC22 rassemble plusieurs groupes de travail, chacun portant sur un
langage spcifique, ou sur des considrations indpendantes des langages. On peut ainsi
citer, par exemple :
JTC1/SC22/WG9 pour Ada ;
JTC1/SC22/WG14 pour le C ;
JTC1/SC22/WG21 pour le C++.
Comme pour toute norme internationale, c'est l'ISO qui dcide des modalits de sadistribution. Comme la grande majorit des normes ISO, celle-ci n'est pas en libre
distribution, mais en vente[2] . Le lecteur dsirant acheter un exemplaire de la norme peut
http://fr.wikipedia.org/wiki/JTC1http://fr.wikipedia.org/wiki/JTC1http://fr.wikipedia.org/wiki/CEIhttp://fr.wikibooks.org/w/index.php?title=Cat%C3%A9gorie:Chttp://fr.wikipedia.org/wiki/POSIX8/6/2019 programmation_C
6/123
Introduction 6
le faire sur le site officiel de l'ISO, par exemple.
Les corrections, ou questions, concernant la norme sont diffuses individuellement par le
WG14 sur leur site sous le nom de Defect Report (DR), et rassembles pour publication
offcielle dans des rectificatifs techniques ou Technical Corrigenda (TC). Deux ont t
publis pour le C99, en 2001 et 2004.
Par ailleurs, les brouillons (ou drafts) de la norme appartiennent au groupe de travail, quipeut dcider de les publier. C'est le cas des documents n869, qui est le dernier brouillon
disponible avant la publication de C99, et n1124, correspondant au C99 auquel ont t
ajouts les TC1 et TC2 (le TC3 ayant t publi en 2007).
On pourra noter que, tout comme l'ANSI l'a fait pour le C89, le WG14 a publi unRationale,
qui est un commentaire de la norme C99. Ces deux textes (en anglais, toujours) peuvent
tre intressants pour comprendre les motivations de certains choix dans l'volution du
langage.
Tous ces documents sont disponibles sur le site officiel du groupe de travail (les URLs et
rfrences se trouvent dans la bibliographie la fin de ce livre).
Toutefois, il faut bien noter qu'une norme est un texte trs technique, qui sert de rfrence,
et est trs loin d'tre un texte pdagogique. Un dbutant fera mieux de lire un ouvrage
comme ce wikilivre pour apprendre le C que lire directement la norme, au risque d'tre
rapidement dcourag. Le prsent ouvrage est construit de manire ne pas avoir
recourir au texte de la norme, et n'y fera rfrence que rarement, mais le lecteur intress
et averti pourra y vrifier des points complexes qui ne seront pas dtaills ici.
C et C++Ce livre ne porte pas sur le C++, mais ces deux langages tant d'apparence trs proches. Il
convient, pour viter la confusion au lecteur dsireux d'apprendre l'un ou l'autre, deprciser qu'ils sont trs diffrents et que, si la connaissance de l'un peut aider
l'apprentissage de l'autre, ils ne doivent pas tre confondus. L'ide du langage qui est
devenu C++ a t lance par Bjarne Stroustrup en 1979, dans un souci de faire voluer le
C de manire le rendre plus robuste . L'apport le plus visible de cette volution est que
le C++ est orient objet, alors que le C est procdural, mais ce n'est pas le seul.
Le langage C++ s'est cr partirdu C puis, rapidement, en parallle lui, et en 1998 est
devenu une norme ISO au mme titre que le C. Les groupes de travail respectifs du C et du
C++ communiquent rgulirement dans le but d'assurer une certaine compatibilit entre
les deux langages. De fait, un certain nombre d'ides issues des rflexions autour du C++
se sont vues intgres dans la norme C99[3] . Cependant, la croyance populaire selon
laquelle le C est un sous-ensemble du C++, ou qu'utiliser un compilateur C++ pour un
programme C ne pose pas de problme, est fausse, et plus d'un titre :
un source strictement conforme du point de vue du C peut tre invalide au sens du
C++[4] ;
un source qui est la fois strictement conforme pour le C et le C++ peut avoir un
comportement diffrent dans ces deux langages[5] .
Durant l'apprentissage du C, le lecteur devra donc faire attention. Un certain nombre
d'diteurs, mettant profit la grande proximit des deux langages, distribuent ensemble un
compilateur C et un compilateur C++, en appelant parfois l'ensemble C/C++, ce quientrane une grande confusion chez les utilisateurs, qui ont parfois du mal savoir quel est
http://fr.wikipedia.org/wiki/Bjarne_Stroustrup8/6/2019 programmation_C
7/123
Introduction 7
le langage dans lequel ils travaillent. L'utilisateur doit donc apprendre comment fonctionne
son implmentation, pour dterminer quel(s) langage(s), norme(s) et extension(s) elle
supporte, et comment le faire fonctionner dans l'un ou l'autre mode.
Une liste de compilateurs, avec les supports des normes, est rfrence en Bibliographie.
Pourquoi apprendre le langage C ? Avec son approche bas-niveau, le C permet d'obtenir des programmes trs optimiss,
pratiquement autant que s'ils avaient t crits directement en assembleur. Avec un peu
d'effort, il est mme possible d'utiliser une approche oriente objet, au prix d'une certaine
rigueur que le langage et les compilateurs, dans une certaine mesure, sont trs loin
d'imposer.
Les systmes d'exploitation pour ordinateur de bureau les plus rpandus actuellement sont
Windows de Microsoft, Mac OS X d'Apple, et GNU/Linux. Ils sont tous trois crits en
langage C. Pourquoi ? Parce que les systmes d'exploitation tournent directement au
dessus du matriel de la machine. Il n'y a pas de couche plus basse pour grer leurs
requtes. l'origine, les systmes d'exploitation taient crits en assembleur, ce qui les
rendait rapides et performants. Toutefois, crire un OS en assembleur est une tche
pnible et cela produit du code qui ne peut s'excuter que sur une seule architecture
processeur, comme l'Intel X86 ou l'AMD 64. crire un OS dans un langage de plus haut
niveau, comme le langage C, permet au programmeur de porter son systme d'exploitation
sur une autre architecture sans avoir tout rcrire.
Kenneth Thompson ( gauche) et Dennis Ritchie ( droite), les
crateurs du langage C
Mais pourquoi utiliser le C et non
Java, Basic ou Perl ?
Principalement cause de la
gestion de la mmoire. ladiffrence de la plupart des autres
langages de programmation, le
langage C permet au
programmeur de grer la mmoire
de la manire qu'il aurait choisie
s'il avait utilis l'assembleur. Les
langages comme le Java et le Perl
permettent au programmeur de ne
pas avoir se soucier de
l'allocation de la mmoire et despointeurs. C'est en gnral un
point positif, car il est assez pnible et inutile de devoir se soucier de la gestion de la
mmoire lorsqu'on crit un programme de haut niveau comme un rapport sur les rsultats
trimestriels.
Cependant lorsqu'on parle d'crire un programme de bas niveau comme la partie du
systme d'exploitation qui s'occupe d'envoyer la chane d'octets correspondant notre
rapport trimestriel depuis la mmoire de l'ordinateur vers le bufferde la carte rseau afin
de l'envoyer vers une imprimante rseau, avoir un accs direct la mmoire est
fondamental ce qui est impossible faire dans un langage comme Java par exemple. Les
compilateurs C produisent de plus trs souvent un code rapide et performant.
http://fr.wikibooks.org/w/index.php?title=Fichier:Ken_n_dennis.jpg8/6/2019 programmation_C
8/123
Introduction 8
Est-ce vraiment si merveilleux que le langage C soit un langage si rpandu ? Par effet
domino, la gnration suivante de programmes suit la tendance de ses anctres. Les
systmes d'exploitation crits en C ont toujours des librairies crites en C. Ces
bibliothques systme sont leur tour utilises pour crire des bibliothques de plus haut
niveau (comme OpenGL ou GTK) et le programmeur de ces bibliothques dcide souvent
d'utiliser le mme langage que celui utilis par ces bibliothques systme. Les
dveloppeurs d'applications utilisent ces bibliothques de haut niveau pour crire des
traitements de texte, des jeux, les lecteurs multimdia, etc... La plupart d'entre eux
choisiront d'utiliser pour leur programme le mme langage que les bibliothques de haut
niveau. Et le schma se reproduit l'infini...
Rfrences[1] Le lecteur intress peut rcuprer la dernire version de travail sur la page "projects" du site du WG.
[2] Certaines normes sont rendues disponibles gratuitement et en libre tlchargement sur internet, mais leur
nombre est relativement faible par rapport l'ensemble des normes existantes.
[3] On peut citer comme exemple les commentaires de fin de ligne, les macros nombre variable d'arguments, les
dclarations de symboles n'importe quel endroit et le mot cl inline pour pallier la prcarit des macros
[4] L'exemple le plus simple serait la dfinition d'une variable ayant pour identifieur un mot rserv du C++,
comme int class;.
[5] Le lecteur curieux pourra se rfrer cet article (http://david.tribble.com/ text/cdiffs.htm) de David R.
Tribble, en anglais, qui numre les diffrences entre C99 et C++98.
Bases du langage
Bonjour!L'un des plus petits programmes possible en langage C est :
#include
intmain(void)
{
printf("Bonjour !\n");
return0;
}
(Les numros de lignes ont t ajouts pour la lisibilit, mais ne font pas partie du
programme.)
Ce programme a pour seule fonction d'afficher le texte Bonjour ! suivi d'un retour la
ligne. Voici la description de chaque ligne qui le compose :
#include
Inclusion de l'en-tte nomm . Il est li la gestion des entres et sorties
(STanDard Input Output, entres/sorties standards) et contient, entre autres, la dclaration
de la fonction printf permettant d'afficher du texte format.
int main(void)
http://david.tribble.com/text/cdiffs.htm8/6/2019 programmation_C
9/123
Bases du langage 9
Dfinition de la fonction principale du programme, main (principal en anglais). Il s'agit de
la fonction appele par le systme d'exploitation au dmarrage du programme, tout
programme en C doit donc la dfinir. La partie entre parenthses spcifie les paramtres
que reoit le programme : ici, le programme n'utilisera aucun paramtre, ce qui est spcifi
en C avec le mot-cl void (vide). La partie gauche du nom de la fonction main spcifie le
type renvoy par la fonction : la fonction main est dfinie par la norme C comme renvoyant
une valeur entire, de type int (pour integer, entier), au systme d'exploitation.
{
Dbut de la dfinition de la fonction main.
printf("Bonjour !\n");
Invocation de la fonction printf (print formatted, affichage format. La notion de format
sera explique dans le chapitre ddi cette fonction.). La chane Bonjour ! va tre
affiche, elle sera suivie d'un retour la ligne (il est reprsent par \n). return0;
La fonction main a t dfinie comme retournant (to return) une valeur de type int, on
renvoie donc une telle valeur. Par convention, la valeur 0 indique au systme d'exploitation
que le programme s'est termin normalement.
}
Fin de la dfinition de la fonction main.
Ce premier exemple ne dtaille videmment pas tout ce qui concerne la fonction main, ouprintf, par exemple. La suite de l'ouvrage prcisera les points ncessaires dans les
chapitres appropris (voir par exemple le paragraphe la fonction main du chapitre
Fonctions et procdures, ou le paragraphe Sorties formates du chapitreEntres/sorties).
CompilationPour excuter un programme C, il faut pralablement le compiler?.
Tapez le code source du programme Bonjour ! dans un diteur de texte? et sauvegardez-le
sous le nom bonjour.c (l'extension .c n'est pas obligatoire, mais est usuelle pour un
fichier source en C). Ouvrez une fentre de commandes (terminal sous Unix, commandesMS-DOS sous Windows), et placez-vous dans le rpertoire o est sauvegard votre fichier.
Pour compiler avec le compilateur GNU CC, il faut taper la commande :
cc bonjour.c
D'autres compilateurs pour le langage C peuvent tre utiliss. La compilation du
programme produira un fichier excutable (a.out sous Unix, a.exe sous Windows) qui
peut tre excut (en tapant ./a.out sous Unix, a sous Windows).
http://fr.wikibooks.org/w/index.php?title=Programmation_C/Glossaire%23%C3%A9diteur_de_textehttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Glossaire%23compilerhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Entr%C3%A9es/sorties%23Sorties_format%C3%A9eshttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Fonctions_et_proc%C3%A9dures%23La_fonction_main8/6/2019 programmation_C
10/123
Bases du langage 10
lments de syntaxe
Identificateurs
Les identificateurs commencent par une lettre ou le caractre soulign ("_") et peuvent
contenir des lettres, des chiffres et le caractre soulign (cependant, les identificateurs
commenant par deux caractres souligns, ou un caractre soulign suivi d'une majusculesont rservs au compilateur, et ne doivent pas tre utiliss dans un programme
ordinaire ). Tous les mots-cls ainsi que les symboles (variables, fonctions, champs, etc.)
sont sensibles la casse des lettres. Quelques exemples d'identificateurs valides :
toto
_coin_coin76
Mots rservs du langage
Le langage, dans la norme C90, possde 32 mots rservs (ou mots-cls) qui ne peuvent pastre utiliss comme identificateurs. La norme C99 y a ajout 5 mots-cls. Le tableau
ci-dessous les liste tous, avec la mention C99 pour indiquer ceux dfinis uniquement dans
la dernire version :
auto break case char const continue default do
double else enum extern float for goto if
inline (C99) int long register restrict (C99) return short signed
sizeof static struct switch typedef union unsigned void
volatile while _Bool (C99) _Complex
(C99)
_Imaginary (C99)
Un programme C90 peut dfinir inline comme un identifiant de variable ou de fonction,
par exemple, mais cela est trs dconseill, car un tel programme sera invalide au sens de
la norme C99. Une mise jour du compilateur peut alors faire refuser un tel programme,
alors qu'il l'aurait accept avant. Pour viter de telles situations, il faut considrer tous les
mots-cls du tableau prcdent comme rservs, quel que soit le compilateur ou la norme
utiliss.
Commentaires
Les commentaires commencent par /* et se terminent par */, ils ne peuvent pas treimbriques :
/* ceci est un commentaire */
/*
ceci est aussi un commentaire
*/
/* /* ceci est encore un commentaire */
http://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Bool%C3%A9enshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_It%C3%A9rations%23Boucle_whilehttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Qualificateur_%27volatile%27http://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Videhttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Entiershttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Unionshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23D%C3%A9finitions_de_synonymes_de_types_%28typedef%29http://fr.wikibooks.org/w/index.php?title=Programmation_C_Tests%23Test_switchhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Structureshttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Classe_%27static%27http://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Entiershttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Entiershttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Qualificateur_%27restrict%27http://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Classe_%27register%27http://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23R%C3%A9elshttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Entiershttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Fonctions_et_proc%C3%A9dures%23Fonction_inlinehttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Tests%23Test_ifhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_It%C3%A9rations%23Saut_inconditionnel_%28goto%29http://fr.wikibooks.org/w/index.php?title=Programmation_C_It%C3%A9rations%23Boucle_forhttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23R%C3%A9elshttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Classe_%27extern%27http://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23%C3%89num%C3%A9rationshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Tests%23Test_ifhttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23R%C3%A9elshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_It%C3%A9rations%23Boucle_do-whilehttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Tests%23Test_switchhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_It%C3%A9rations%23Arr%C3%AAt_et_continuation_des_boucleshttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Qualificateur_%27const%27http://fr.wikibooks.org/w/index.php?title=Programmation_C/Types_de_base%23Caract%C3%A8reshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Tests%23Test_switchhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_It%C3%A9rations%23Arr%C3%AAt_et_continuation_des_boucleshttp://fr.wikibooks.org/w/index.php?title=Programmation_C/Classe_de_stockage%23Classe_%27auto%278/6/2019 programmation_C
11/123
Bases du langage 11
Ce code contient une erreur volontaire !
/* /* */ ceci nest pas un commentaire */
Inclure des commentaires pertinents dans un programme est un art subtil. Cela ncessite
un peu de pratique pour savoir guider les lecteurs et attirer leur attention sur certaines
parties dlicates du code. Pour faire court, on ne saurait trop que rappeler ce clbre vers
de Nicolas Boileau, qui disait que ce que l'on conoit bien, s'nonce clairement et les mots
pour le dire arrivent aisment (Art Potique, 1674). Ou encore, pour adopter une
approche plus pragmatique : si un programmeur a du mal commenter (expliquer,
spcifier) le fonctionnement d'un passage de code, c'est que le code est mal conu et qu'il
serait bnfique de le rcrire plus lisiblement.
Attention! Les commentaires ne devraient pas tre employs pour dsactiver certaines
parties du code. Cette technique dissuade un programmeur d'en inclure puisque le langage
C ne permet pas d'imbriquer les commentaires. Pour cela, le prprocesseur dispose
d'instructions ddies, qui permettent heureusement de dsactiver du code en laissant les
commentaires.Le // ajoute la possiblit de placer un commentaire d'une seule ligne, partir du //
jusqu' la fin de la ligne :
// commentaire
instruction; // autre commentaire
Cependant, ces commentaires la C++ sont apparus dans C99, et ne sont pas permis
en C90.
Instructions
Les instructions se terminent par un point-virgule (;), on peut placer autant d'instructions
que l'on veut sur une mme ligne (mme si ce n'est pas conseill pour la lisibilit du code).
Les blocs d'instructions commencent par une accolade ouvrante ({) et se terminent par une
accolade fermante (}). Les instructions doivent obligatoirement tre dclares dans
une fonction : il est impossible d'appeler une fonction pour initialiser une variable globale
par exemple (contrairement au C++).
/* une instruction */
i =1;
/* plusieurs instructions sur la mme ligne */i =1; j =2; printf("bonjour\n");
/* un bloc */
{
int i;
i =5;
}
/* l'instruction vide */
;
http://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svg8/6/2019 programmation_C
12/123
Bases du langage 12
Dans la mesure o le compilateur ne se soucie pas des blancs (espaces et retours la
ligne), vous pouvez formater votre code comme vous l'entendez. Il y a beaucoup de religion
concernant les styles d'indentation, mais pour faire court et viter les guerres saintes, on
ne saurait trop conseiller que d'utiliser le mme nombre de blancs par niveau d'imbrication
de bloc.
noter que l'instruction vide tant valide en C, on peut donc pratiquement rajouter autantde point-virgules que l'on veut. Le point-virgule ne sert pas uniquement marquer la fin
des instructions, les compilateurs l'utilisent gnralement comme caractre de
synchronisation, suite une erreur dans un programme source. En fait, en gnral,
lorsqu'une erreur est dtecte, les compilateurs ignorent tout jusqu'au prochain
point-virgule. Ce qui peut avoir des consquences assez dramatiques, comme dans
l'exemple suivant :
Ce code contient une erreur volontaire !
inttraite_arguments( int nb, char* argv[] )
{
/* ... */
return0
}
intmain( int nb, char* argv[] )
{
int retour;
retour = traite_arguments( nb, argv );
/* ... */
}
On notera l'absence de point-virgule la fin de l'instruction return la fin de la fonction
traite_arguments. Ce que la plupart des compilateurs feront dans ce cas sera d'ignorer
tout jusqu'au prochain point-virgule. On se rend compte du problme : on a saut une
dclaration de fonction (avec ses deux paramtres) et une dclaration de variable. Ce qui
veut dire qu'une cascade d'erreurs va suivre suite l'oubli... d'un seul caractre (;) !
Dclarations de variables
T var1, var2, ..., varN;
Cette ligne dclare les variables var1, var2, ..., varNde type T. Une variable est dite locale,
si elle est dfinie l'intrieur d'une fonction et globale si dfinie en-dehors.
Par exemple:
int jour; /* 'jour' est une variable globale, de type entier */
intmain(void)
{
double prix; /* 'prix' est une variable locale la fonction
'main', de type rel */ return0;
http://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svg8/6/2019 programmation_C
13/123
Bases du langage 13
}
Variables locales
Les variables locales (aussi appeles automatiques) ne sont visibles que dans le bloc dans
lequel elles sont dfinies, et n'existent que durant ce bloc. Par exemple :
Ce code contient une erreur volontaire !intfonction(int n)
{
int i; /* i est visible dans toute la fonction */
i = n +1;
{ /* dbut d'un nouveau bloc */
int j; /* j est visible dans le nouveau bloc *seulement* */
j =2* i; /* i est accessible ici */
}
i = j; /* ERREUR : j n'est plus accessible */
return i;}
Le code prcdent accde i depuis un bloc contenu dans le bloc o i a t dfini, ce qui
est normal. Puis il essaye d'accder la valeur de la variable jen-dehors du bloc o elle
t dfinie, ce qui est une erreur.
Les variables locales ne sont pas initialises automatiquement et contiennent
donc, aprs leur dclaration, une valeur alatoire. Utiliser une telle valeur peut causer
un comportement alatoire du programme. Le programme suivant essaye d'afficher la
valeur d'une telle variable, et on ne peut savoir l'avance ce qu'il va afficher. Si on le lance
plusieurs fois, il peut afficher plusieurs fois la mme valeur aussi bien qu'il peut afficherune valeur diffrente chaque excution:
Ce code contient une erreur volontaire !
#include
intmain(void)
{
int n;
printf("La variable n vaut %d\n", n);
return0;}
Avant la normalisation ISO C99, les dclarations de variables locales devaient
obligatoirement tre places juste au dbut d'un bloc et s'arrtaient la premire
instruction rencontre. Si une dclaration est faite au-del, une erreur sera retourne.
Suivant la norme C99, les dclarations peuvent se trouver n'importe o dans un bloc. Par
exemple, le code suivant est correct suivant la norme C99, mais pas suivant la norme C90,
car la variable a est dfinie aprs l'instruction puts("Bonjour !");:
intma_fonction(int n)
{puts("Bonjour !");
http://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svghttp://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svg8/6/2019 programmation_C
14/123
Bases du langage 14
int a; /* Valide en C99, invalide en C90 */
/* autre chose... */
return a;
}
Variables globales
Une attention particulire doit tre porte aux variables globales, souvent source de
confusion et d'erreur. Utilisez des noms explicites, longs si besoin et limitez leur usage au
seul fichier o elles sont dclares, en les dclarants statiques.
Les variables globales sont initialises avant que la fonction main s'excute. Si le
programmeur ne fournit pas de valeur initiale explicitement, chaque variable reoit une
valeur par dfaut suivant son type:
un nombre (entier, rel ou complexe) est initialis 0;
les pointeurs sont initialiss NULL;
pour une structure, l'initialisation se fait rcursivement, chaque membre tant initalis
suivant les mmes rgles; pour une union, le premier membre est initialis suivant ces rgles.
Pour initialiser explicitement une variable globale, on ne peut utiliser que des constantes;
en particulier, on ne peut appeler de fonction, contrairement d'autres langages.
Ce code contient une erreur volontaire !
intjour_courant(void)
{
/* retourne le n du jour courant */
}
int jour = jour_courant(); /* ERREUR ! */
intmain(void)
{
/* ... */
return0;
}
Le code prcdent ne pourra pas compiler, car on ne peut appeler directement
jour_courant() pour initialiser jour. Si vous avez besoin d'un tel comportement, unesolution est de faire l'initalisation explicite dans main:
intjour_courant(void)
{
/* retourne le n du jour courant */
}
int jour; /* 'jour' est initialis 0 *avant* le dbut de 'main' */
intmain(void)
{jour = jour_courant();
http://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svghttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Unionshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Structures8/6/2019 programmation_C
15/123
Bases du langage 15
/* ... */
return0;
}
Traitements des ambiguts
Le C utilise un mcanisme lgant pour lever des constructions syntaxiques en apparenceambigus. L'analyse des mots (lexmes, token en anglais) se fait systmatiquement de la
gauche vers la droite. Si plusieurs lexmes peuvent correspondre une certaine position, le
plus grand aura priorit. Considrez l'expression valide suivante :
a+++b;
Ce genre de construction hautement illisible et absconse est bien videmment viter,
mais illustre parfaitement bien ce mcanisme. Dans cet exemple, le premier lexme trouv
est bien sr l'identificateur 'a' puis le compilateur a le choix entre l'oprateur unaire '++', ou
l'oprateur binaire '+'. Le plus grand tant le premier, c'est celui-ci qui aura priorit.
L'instruction se dcompose donc en :(a ++) + b;
Types de baseLe C est un langage typ statiquement : chaque variable, chaque constante et chaque
expression, a un type dfini la compilation. Le langage lui-mme fournit des types
permettant de manipuler des nombres (entiers, rels ou complexes) ou des caractres
(eux-mmes tant manipuls comme des entiers spciaux), et permet de construire destypes plus complexes partir de ces premiers, par exemple en groupant des donnes de
mme type en tableaux, ou des donnes de types diffrents dans des structures. Dans ce
chapitre, nous tudierons les types de base fournis par le C, l'tude des types complexes
tant faite dans la suite du livre.
EntiersIl y a cinq types de variables entires ( integer en anglais) :
char ;
short int, ou plus simplement short ; int ;
long int, ou long ;
long long int, ou long long (ce type a t ajout depuis la norme C99).
Comme voqu en introduction, le type caractre char est particulier, et sera tudi en
dtail plus bas.
Les types entiers peuvent prendre les modificateurs signed et unsigned qui permettent
respectivement d'obtenir un type sign ou non sign. Ces modificateurs ne changent pas la
taille des types. Le langage ne dfinit pas exactement leur tailles, mais dfinit un domaine
de valeurs minimal pour chacun.
La norme C tient compte des anciennes reprsentations des nombres signs telles que le
signe+valeur absolue et le complment 1. Ces deux reprsentations sont brivement
http://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Structureshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_de_base%23Caract%C3%A8reshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_de_base%23R%C3%A9elshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_de_base%23Entiers8/6/2019 programmation_C
16/123
Types de base 16
expliques ci-dessous :
Signe+valeur absolue (SVA)
Un bit contient le signe du nombre (par ex: 0 pour +, 1 pour -), les autres bits sont
utiliss pour la valeur absolue. On peut donc reprsenter 0 de deux manires : +0
(000...000) ou -0 (100..000). Sur N bits on peut donc reprsenter tout nombre entre
-(2N
-1) (111...111) et +(2N
-1) (011...111).Complment 1 (CPL1)
Les bits des nombres ngatifs sont inverss. On peut donc reprsenter 0 de deux
manires : +0 (000...000) ou -0 (111..111). Sur N bits on peut donc reprsenter tout
nombre entre -(2N-1) (100...000) et +(2N-1) (011...111).
Ces deux reprsentations peuvent reprsenter la valeur nulle de deux manires diffrentes.
La reprsentation moderne des nombres ngatifs utilise le complment 2 (CPL2) qui
consiste reprsenter les nombres ngatifs comme le complment 1 et en ajoutant 1. Sur
un nombre fixe de bits, la valeur 0 n'a qu'une seule reprsentation : +0 (000...000) et -0
(111...111 + 1 = (1)000...000) ont deux reprsentations identiques. Sur N bits on peut doncreprsenter tout nombre entre -(2N) (100...000) et +(2N-1) (011...111). Cette reprsentation
possde donc un domaine plus large.
Le tableau ci-dessous donne le domaine des valeurs quel que soit la reprsentation utilise
(SVA, CPL1 ou CPL2) :
Domaines de valeurs minimaux des types entiers (C90 et C99)
Type Borne infrieure Borne
infrieure
(formule)
Borne suprieure Borne
suprieure
(formule)
signed char -127 -(27-1) +127 27-1
unsigned char 0 0 +255 28-1
short -32767 -(215-1) +32767 215-1
unsigned short 0 0 +65535 216-1
int -32767 -(215-1) +32767 215-1
unsigned int 0 0 +65535 216-1
long -2147483647 -(231-1) +2147483647 231-1
unsigned long 0 0 +4294967295 232-1
long long(C99) -9223372036854775807 -(263-1) +9223372036854775807 263-1
unsigned long long
(C99)
0 0 +18446744073709551615 264-1
Cette table signifie qu'un programme peut utiliser sans problme une variable de type int
pour stocker la valeur 215-1, quelque soit le compilateur ou la machine sur laquelle va
tourner le programme.
Par contre, une implmentation C peut fournir des domaines de valeurs plus larges que
ceux indiqus au-dessus :
8/6/2019 programmation_C
17/123
Types de base 17
Les domaines indiqus pour les nombres signs dans le tableau prcdent sont ceux
d'une implmentation par complment 1, ou par signe et valeur absolue. Pour le
complment 2, la borne infrieure est de la forme -2N, ce qui autorise une valeur
supplmentaire (ex: int de -215 +215-1, soit de -32768 +32767),
un int implment sur 32 bits pourrait aller de -(231-1) 231-1, par exemple[1] , et un
programme tournant sur une telle implmentation peut alors utiliser ces valeurs, mais il
perdrait en portabilit.
Domaines de valeurs des types entiers reprsents en complment 2 (CPL2)
Type Borne infrieure Borne
infrieure
(formule)
Borne suprieure Borne
suprieure
(formule)
signed char -128 -(27) +127 27-1
unsigned char 0 0 +255
2
8
-1short -32768 -(215) +32767 215-1
unsigned short 0 0 +65535 216-1
int -32768 -(215) +32767 215-1
unsigned int 0 0 +65535 216-1
long -2147483648 -(231) +2147483647 231-1
unsigned long 0 0 +4294967295 232-1
long long(C99) -9223372036854775808 -(263) +9223372036854775807 263-1
unsigned long long
(C99)
0 0 +18446744073709551615 264-1
Par ailleurs, une relation d'ordre entre ces domaines de valeurs est garantie ; qui peut tre
exprime ainsi :
domaine(char) domaine(short) domaine(int) domaine(long)
domaine(long long)
Cela signifie que toutes les valeurs possibles pour une variable du type char sont aussi
utilisables pour les autres types; mais aussi que, par exemple, une valeur valide pour letype int peut ne pas tre reprsentable dans une variable de type short.
Si vous ne savez pas quel type donner une variable de type entier, le type int est par
dfaut le meilleur choix ( condition que votre donne ne dpasse pas 215-1) : ce type est la
plupart du temps reprsent au niveau matriel par un mot machine , c'est--dire qu'il
est adapt la taille que la machine peut traiter directement (il fait usuellement 32 bits sur
un PC 32 bits, par exemple). Cela permet un traitement plus rapide par le matriel. De plus,
beaucoup de bibliothques (que ce soit celle fournie par le langage C ou d'autres) utilisent
ce type pour passer des entiers, ce qui fait que l'utilisation de ces bibliothques sera plus
aise.
Par ailleurs, un utilisateur peut connatre les domaines de valeurs exacts de sa machine en
utilisant l'en-tte .
8/6/2019 programmation_C
18/123
Types de base 18
Portabilit apporte par C99
L'incertitude sur l'intervalle de valeur de chaque type en fonction de la machine peut
s'avrer extrmement gnante, pour ne pas dire rdhibitoire. En effet, certains
programmes peuvent ncessiter un type de donnes de taille fixe et cependant tre
destins tre portables. Pour ces programmes, les types entiers du C ne sont pas
suffisants. Beaucoup d'extensions ont t rajoutes pour dfinir explicitement des typesentiers intervalle fixe (8, 16, 32 bits...) partir des types de base, avec une nomenclature
loin d'tre homogne d'un compilateur l'autre (ce qui, loin de rsoudre le problme, ne
faisait que le dplacer).
La norme ISO C99 dcide une bonne fois pour toute de dfinir, dans l'en-tte ,
plusieurs nouveaux types oN reprsente un nombre entier dfinissant la taille requise en
bit :
des types implments optionnellement sur certaines architectures ( viter ?) ;
entiers signs ou non et de longueur exacte : uintN_t et intN_t ;
entiers pouvant contenir un pointeur : intptr_t et uintptr_t ;
des types requis par toutes les architectures respectant la norme C99 ;
entiers devant tre plus grand que N bits au moins : int_leastN_t et uint_leastN_t
;
entiers rapides calculer et plus grand que N bits au moins : int_fastN_t et
uint_fastN_t ;
plus grand entier : intmax_t et uintmax_t.
Cet en-tte dfinit aussi des constantes pour les valeurs minimales et maximales de chaque
type.
L'include dfinit les constantes symboliques utiliser pour imprimer ces
nouveaux types avec les fonctions de la famille de printf (PRIxxx) et les lire avec celles descanf (SCNxxx).
Constantes numriques entires
Il existe diffrentes suites de caractres qui sont reconnues comme tant des constantes
numriques entires :
un nombre en notation dcimale : une suite de chiffres (0-9) ;
le caractre 0 suivi d'un nombre en notation octale : une suite de chiffres compris
entre 0 et 7 ;
les caractres 0x suivi d'un nombre en notation hexadcimale : une suite de chiffreset des lettres a, b, c, d, e, f (ou A, B, C, D, E, F).
Par dfaut, une constante numrique entire est de type int et, si sa valeur est trop
grande pour le type int, elle prend celle du type plus grand suffisant. Comme les
domaines de valeurs des types peuvent varier suivant la machine, le type effectif d'une
constante peut lui aussi varier. Cela peut s'avrer problmatique lors de passage de
paramtres des fonctions nombre variable d'arguments, par exemple. cause de cela, il
est recommand de forcer le type de la constante en le postfixant des attributs suivants :
U : la constante est non-signe (voir la section promotion pour comprendre les
implications) ;
L : la constante est de type long au lieu de int ; LL est une nouveaut C99 pour les constantes de type long long.
http://fr.wikipedia.org/wiki/en:inttypes.hhttp://fr.wikipedia.org/wiki/en:stdint.h8/6/2019 programmation_C
19/123
Types de base 19
U peut tre combin L et LL pour obtenir les types unsigned long et unsigned long
long, respectivement. Lorsqu'une constante est suffixe, mais que sa valeur est trop grande
pour le type demand, le mme processus de recherche de type assez grand est
utilis[2] .
Dbordement
Sur une machine donne, un type entier a un domaine de valeurs fixe. Considrons qu'on
travaille sur un PC en 32 bits, en complment 2 : sur un tel ordinateur, le type int varie
souvent de -231 231-1. Cela permet de manipuler sans problme des valeurs dans ce
domaine. Par contre, si on utilise des valeurs hors du domaine, par exemple 232, et qu'on
essaye de la stocker dans une variable de type int sur une telle machine, que se passe-t-il
?
La rponse dpend du type:
Si on essaye d'enregistrer une valeur hors domaine dans une variable de type sign
(comme dans l'exemple), la conversion n'est pas dfinie par le langage. Cela signifie que
tout peut arriver. Si on essaye d'enregistrer une valeur hors domaine dans une variable de type non sign
(unsigned long, par exemple), la conversion se fait modulo la valeur maximale
reprsentable par ce type + 1.
Exemples : On suppose que le type unsigned char est cod sur 8 bits. Alors une valeur de
ce type peut aller de 0 28-1, soit 255. Par la rgle prcdente, les conversions se feront
donc modulo 255 + 1, soit 256. On considre le programme suivant :
#include
intmain(void){
unsignedchar c =300;
/* %hhu sert dire printf() qu'on veut afficher un unsigned char
*/
printf("La variable c vaut %hhu.\n", c);
c =-5;
printf("La variable c vaut %hhu.\n", c);
return0;
}
Le rsultat du programme est :
La variable c vaut 44.
La variable c vaut 251.
En effet, on a 300 - 256 = 44 et -5 + 256 = 251.
De mme :
#include
intmain(void)
{
signedchar c =300;
8/6/2019 programmation_C
20/123
Types de base 20
/* %hhd sert dire printf() qu'on veut afficher un signed char */
printf("La variable c vaut %hhd.\n", c);
c =-300;
printf("La variable c vaut %hhd.\n", c);
return0;
}
Le rsultat du programme peut alors tre :
La variable c vaut 44.
La variable c vaut -44.
Sur une telle machine, les types signs sont traits de la mme manire que les types non
signs.
Si vous essayez de compiler ces deux programmes, votre compilateur pourra dtecter les
dbordements et vous en avertir (GCC le fait).
RelsLes rels sont approxims par des nombres virgule flottante. Comme dans le cas des
entiers, il existe plusieurs types de nombre virgule flottante. En voici la liste trie par
prcision croissante :
float ;
double ;
long double.
La norme C90 tait assez floue concernant les nombres virgule flottante, leurs
reprsentations, la prcision des oprations, etc., ce qui fait que c'tait un des domaines o
la conception de programmes utilisant les nombres flottants tait chose peu aise. Le C99 a
clarifi les choses en prcisant qu'une implmentation C devait respecter la norme IEC
60559:1989 Arithmtique binaire en virgule flottante pour systmes
microprocesseur. Cette norme (drive de IEEE 754) dfinit des formats de donnes pour
les nombres virgule flottante, ainsi que des oprations et fonctions sur ces nombres. Elle
garantit, entre autres :
que certains types de donnes auront toujours le mme format ;
et que les calculs effectus sur un type de donne donneront toujours le mme rsultat.
Elle dfinit de plus comment sont grs les cas exceptionnels, comme les infinis, les NaN
(pourNot a Number, rsultant par exemple de la division 0/0), etc.Les types flottants du C correspondent aux type IEC 60559 de la manire suivante :
float : simple prcision
double : double prcision
long double : suivant l'implmentation, soit la double prcision tendue, soit un type
non-IEC 60559 (mais de prcision au moins gale double), soit double prcision.
http://fr.wikipedia.org/wiki/IEEE_7548/6/2019 programmation_C
21/123
Types de base 21
Constantes relles
Une suite de caractres reprsente une constante virgule flottante si :
c'est une suite de chiffres spare par un caractre point , cette sparation pouvant
s'effectuer n'importe quel endroit de la suite (0.0, .0 et 0. reprsentent tous les trois
la valeur 0 de type double) ;
un nombre suivi d'un caractre e suivi d'un entier.Dans le deuxime cas, le nombre peut tre soit un entier, soit un rel du premier cas.
Les constantes sont de type double par dfaut. Pour demander le type float, il faut la
suffixer par f ou F, et pour le type long double par l ou L.
Arithmtique
Une attention particulire doit tre porte sur la prcision des types rels. Ces diffrents
types ne font qu'approximer l'ensemble des nombres rels, avec une prcision finie. Des
erreurs d'arrondis sont prvoir, ce qui est trs problmatique pour des domaines qui n'en
tolrent pas (notamment pour les applications financires, il est conseill de ne pas utiliserde calcul en virgule flottante).
Le type float en particulier a une prcision minimale, qui est bien souvent insuffisante.
Voici un exemple classique d'erreur ne pas faire qui illustre les problmes lis la
prcision des types flottants :
#include
intmain(void)
{
float i =0;
int j;
for (j =0; j
8/6/2019 programmation_C
22/123
Types de base 22
float i = j *0.1;
}
return0;
}
C'est probablement plus coteux, car on effectue un millier de multiplications au lieu d'un
millier d'additions, mais cela permet d'avoir une prcision nettement meilleure que le codeprcdent.
Pour plus d'informations sur ce domaine, un wikilivre Arithmtique flottante est disponible.
CaractresLe type permettant de reprsenter un caractre est char. Ce type est un peu plus
particulier que les autres, d'une part parce que sa taille dfinit l'unit de calcul pour les
quantits de mmoire (et donc pour les tailles des autres types du langage) et d'autre part
son domaine de valeur peut grandement varier de manire relativement inattendue.
Par dfinition, la taille du type char, note sizeof(char), vaut toujours 1. Cependant, ilfaut faire attention : contrairement ce qu'on pense souvent, un char au sens du C ne vaut
pas toujours un octet. Il occupera au minimum 8 bits, mais il existe des architectures,
relativement spcialises il est vrai, ayant des char de 9 bits, de 16 bits, voire plus. Mme
si, dans une large majorit des cas, les compilateurs utilisent des char de 8 bits, la fois
par simplicit (les machines modernes fonctionnent gnralement en 8, 16, 32 ou 64 bits)
et pour viter des problmes de portabilit de code (beaucoup de codes C existants
reposent sur l'hypothse que les char font 8 bits, et risqueraient de ne pas marcher sur
une telle architecture)[3] . Par simplification, nous utiliserons donc le terme octet la plupart
du temps dans la suite de ce wikilivre.
Un autre pige de ce type est qu'il peut tre de basesigned ou unsigned, au choix du
compilateur, ce qui peut s'avrer dangereux. Considrez le code suivant :
/* Ce code peut ne pas fonctionner avec certains compilateurs */
char i;
for (i =100; i >=0; i --)
{
/* ... */
}
Dans cet exemple, l'instruction for permet de faire itrer les valeurs entires de i de 100
0, incluses. On pourrait navement penser optimiseren utilisant un type char. Sauf que
si ce type est implicitement unsigned, la condition i >= 0 sera toujours vraie, et tout ce
que vous obtiendrez est une boucle infinie. Normallement tout bon compilateur devrait
vous avertir que la condition est toujours vraie et donc vous permettre de corriger en
consquence, plutt que perdre des heures en dbugage.
http://fr.wikibooks.org/w/index.php?title=Arithm%C3%A9tique_flottante8/6/2019 programmation_C
23/123
Types de base 23
Constantes reprsentant un caractre
Une constante reprsentant un caractre est dlimite par des apostrophes, comme par
exemple 'a'. En fait pour le C, les caractres ne sont ni plus ni moins que des nombres
entiers (ils sont de type int, mais leur valeur tiendra dans un type char), les deux tant
parfaitement interchangeables. Il est tout fait autoris d'crire 'a' * 2 ou 'a' - 32. La
valeur reprsente par cette constante est nanmoins dpendante du systme, mme sidans une crasante majorit des cas, on se retrouvera avec un jeu de caractre compatible
avec ASCII, qui dfinit prcisment les glyphes des caractres de 0 127 [4] . Cet ensemble
est peine suffisant pour couvrir certaines langues latines, seule optique vise l'poque
o il a t dfini, si bien que de nombreuses extensions sont par la suite apparues.
Par exemple le caractre (ligature du o et du e) a pour valeur :
189 dans le jeu de caractres ISO-8859-15 (principalement utilis pour les langues
latines d'Europe) ;
156 sur certaines variantes du jeu de caractres Windows 1252 ;
0xc593 (deux octets) si votre diteur de texte utilise l'UTF-8 ;
207 avec l'encodage Mac Roman (Mac OS 9 et antrieur) ; Et n'a pas d'quivalent en ISO-8859-1 (le caractre 189 est le symbole , le 207 est le
et le 156 n'est pas utilis).
Il s'agit en fait d'un cas particulier d'un sujet trs vaste, qui porte le nom
d'internationalisation. Le langage C reste relativement agnostique ce niveau : les
caractres sont des nombres et les chanes, une simple suite de caractres termine par 0.
Au systme d'interprter les nombres comme il se doit.
Un petit exemple :
#include
intmain(void)
{
printf("Sur votre machine, la lettre 'a' a pour code %d.\n", 'a');
return0;
}
Le programme prcdent donnera le rsultat suivant sur une telle machine :
Sur votre machine, la lettre 'a' a pour code 97.
Caractres spciauxIl existe certaines constantes caractres aux significations particulires :
Constante Caractre
'\'' une apostrophe
'\"' un guillemet
'\?' un point d'interrogation
'\\' un backslash
'\a' un signal sonore (ou visuel)
'\b' un espace arrire
8/6/2019 programmation_C
24/123
Types de base 24
'\f' saut au dbut de la page suivante
'\n' saut de ligne
'\r' un retour chariot
'\t' une tabulation
'\v' une tabulation verticale
De plus, on peut crire n'importe quelle valeur de caractre avec les expressions suivantes :
'\xHH', o chaqueH reprsente un chiffre hexadcimal correspondant au code du
caractre. Par exemple, '\x61' reprsente le caractre 'a' (minuscule) en ASCII (car
97 = 6 * 16 + 1) ;
'\oOO', o chaque O reprsente un chiffre octal correspondant au code du caractre.
Trigraphe
Cette fonctionnalit obscure et peu employe est en gnral viter, car trs souvent
inutile, et peut causer des bugs incomprhensibles au programmeur non averti. Nanmoins,de trs rares programmes peuvent utiliser ce genre de fonctionnalits. Un trigraphe est
simplement une suite de trois caractres dans le code source qui sera remplace par un
seul ; cette fonctionnalit a t ajoute au C pour supporter les architectures dont
l'alphabet ne dispose pas de certains caracres qui sont ncessaires dans la syntaxe du C,
comme les dises ou les accolades.
Les substitutions suivantes sont faites partout dans le code source (y compris les chanes de
caractres) :
Trigraphe Caractre
??= #??( [
??) ]
??< {
??> }
??/ \
??' ^
??! |
??- ~
Voici une manire de rendre illisible un programme utilisant les trigraphes :
??=include
int main(void)
??
noter que, par dfaut, la plupart des compilateurs dsactivent les trigraphes, au cas o
vous ne seriez pas encore dissuad de les utiliser.
8/6/2019 programmation_C
25/123
Types de base 25
Chane de caractresUne chane de caractre, comme son nom l'indique, est une suite de caractres avec la
particularit d'avoir un caractre nul (0) la fin. Une chane de caractre est en fait
implmente en C avec un tableau de type char.
Sous sa forme la plus simple, on dclare une chane comme une suite de caractres entre
guillemets (double quote) :
"Ceci est une chane de caractre";
""; /* Chane vide */
Si la chane est trop longue, on peut aussi la couper sur plusieurs lignes :
"Ceci est une chane de caractre, "/* pas de ; */
"dclare sur plusieurs lignes.";
Deux chanes ctes ctes (modulo les espaces et les commentaires) seront concatnes
par le compilateur. De plus on peut utiliser le caractre barre oblique inverse (\) pour
annuler la signification spciale de certains caractres ou utiliser des caractres spciaux(C.f liste ci-dessus).
"Une chane avec des \"guillemets\" et une barre oblique (\\)\n";
Il est aussi possible d'utiliser la notation hexadcimale et octale pour dcrire des caractres
dans la chane, il faut nanmoins faire attention avec la notation hexadcimale, car la
dfinition peut s'tendre sur plus de 2 caractres. En fait, tous les caractres suivant le \x
et appartenant l'ensemble "0123456789abcdefABCDEF" seront utiliss pour dterminer la
valeur du caractre (du fait que les caractres d'une chane peuvent faire plus qu'un octet).
Cela peut produire certains effets de bords comme :
/* Ce code contient un effet de bord inattendu */
"\x00abcdefghijklmnopqrstuvzxyz"
Ce code n'insrera pas un caractre 0 au dbut de la chaine, mais toute la squence
"\x00abcdef" servira calculer la valeur du caractre (mme si le rsultat sera tronqu
pour tenir dans un type char). On peut viter cela en utilisant la concatnation de chanes
constantes :
"\x00""abcdefghijklmnopqrstuvzxyz"
Enfin, les chanes de caractres faisant appel aux concepts de pointeur, tableau et de zone
mmoire statique, leur utilisation plus pousse sera dcrite dans la section ddie aux
tableaux.
noter la reprsentation obsolte des chanes de caractres multilignes. viter dans la
mesure du possible :
/* Ce code est obsolete et a eviter */
"Ceci est une chane de caractre,\
dclare sur plusieurs lignes";
8/6/2019 programmation_C
26/123
Types de base 26
BoolensLe langage (jusqu' la norme C99) ne fournit pas de type boolen. La valeur entire 0 prend
la valeur de vrit faux et toutes les autres valeurs entires prennent la valeur de vrit
vrai.
La norme C99 a introduit le type _Bool, qui peut contenir les valeurs 0 et 1. Elle a aussi
ajout l'en-tte , qui dfinit le type bool qui est un raccourci pour _Bool, etles valeurs true et false[5] . Nanmoins, ces nouveauts du C99 ne sont pas trs utilises,
les habitudes ayant t prises d'utiliser 0 et diffrent de zro pour les boolens en C.
Nota : toute expression utilisant des oprateurs boolens (voir oprateurs), retourne 1 si
l'expression est vraie et 0 si elle est fausse, ce qui rend quasiment inutile l'usage du type
boolen.
VideEn plus de ces types, le langage C fournit un autre type, void qui reprsente rien, le vide.
Il n'est pas possible de dclarer une variable de type void. Nous verrons l'utilit de ce typelorsque nous parlerons de fonctions et de pointeurs.
Rfrences[1] La norme C contraint les domaines de valeurs des types signs entre -(2N-1) et 2N-1, o N est un entier
quelconque, et les types non signs entre 0 et 2N-1.
[2] La liste des types successifs utiliss pour dterminer le type d'une constante entire a chang entre C90 et
C99. Cela n'a, quasiment tout le temps, aucune incidence, sauf pour le cas d'une constante de valeur trop
grande pour le type long : en C90, le type unsigned long est utilis, alors qu'en C99 le type long long sera
utilis. Une telle valeur sera alors signe dans un cas, et non signe dans l'autre. Dans ce cas, utiliser un suffixe
adapt (UL, LL ou ULL) permet de s'assurer du type de la constante.
[3] La confusion est surtout ne de l'utilisation du mot byte pour dsigner la taille du type chardans la norme,alors que ce mot est utilis dans presque tous les autres domaines de l'informatique pour dsigner un octet.
[4] En-dehors des encodages compatibles avec ASCII, on ne rencontre gure en pratique que la famille de jeux de
caractres EBCDIC, utilise sur des systmes IBM et quelques mainframes.
[5] Ces trois expressions sont dfinies sous formes de macro pour le prprocesseur.
http://fr.wikipedia.org/wiki/EBCDIC8/6/2019 programmation_C
27/123
Classe de stockage 27
Classe de stockageIl est possible de construire des types drivs des types de base du langage en utilisant
plusieurs combinaisons, deux tant illustres dans ce chapitre: les classes de stockage et
les qualificateurs.
Classe de stockageLe langage C permet de spcifier, avant le type d'une variable, un certain nombre de
classes de stockage :
auto : pour les variables locales ;
extern : dclare une variable sans la dfinir ;
register : demande au compilateur de faire tout son possible pour utiliser un registre
processeur pour cette variable ;
static : rend une dfinition de variable persistante.
Les classes static et extern sont, de loin, les plus utilises. register est d'une utilitlimite, et auto est maintenant obsolte.
Une variable, ou un paramtre de fonction, ne peut avoir qu'au plus une classe de stockage.
Classe 'static'
L'effet de la classe 'static' dpend de l'endroit o l'objet est dclar :
Objet local une fonction : la valeur de la variable sera persistante entre les diffrents
appels de la fonction. La variable ne sera visible que dans la fonction, mais ne sera pas
rinitialise chaque appel de la fonction. L'intrt est de garantir une certaine
encapsulation, afin d'viter des usages multiples d'une variable globale. Qui plus est, celapermet d'avoir plusieurs fois le mme nom, dans des fonctions diffrentes.
Exemple :
#include
voidf(void)
{
staticint i =0; /* i ne sera initialis 0 qu'au premier appel
de f */
int j =0; /* j sera initialis chaque fois */;i++;
j++;
printf("i vaut %d et j vaut %d.\n", i, j);
}
intmain(void)
{
f();
f();
f(); return0;
8/6/2019 programmation_C
28/123
Classe de stockage 28
}
Objet global et fonction : comme une variable globale est dj persistante, le mot-cl
static aura pour effet de limiter la porte de la variable ou de la fonction au seul fichier
o elle est dclare, toujours dans le but de garantir un certain niveau d'encapsulation.
faire...
utilisation de static en C99 pour les tableaux en paramtres de fonctions
Classe 'extern'
extern permet de dclarer une variable sans la dfinir. C'est utile pour la compilation
spare, pour dfinir une variable ou une fonction dans un fichier, en permettant des
fonctions contenues dans d'autres fichiers d'y accder.
Toutes les variables globales et fonctions qui ne sont pas dclares (ou dfinies) static
sont externes par dfaut.
static et extern sont employs pour distinguer, dans un fichier C, les objets et fonctions
publics , qui pourront tre accessibles depuis d'autres fichiers, de ceux qui sont privs
et ne doivent tre utiliss que depuis l'intrieur du fichier.
Classe 'register'
Indique que la variable devrait tre stocke dans un registre du processeur. Cela permet de
gagner en performance par rapport des variables qui seraient stockes dans un espace
mmoire beaucoup moins rapide, comme une pile place en mmoire vive.
Ce mot-cl a deux limitations principales :
Les registres du processeur sont forcment limits, aussi bien en nombre qu'en taille. Il
est donc inutile de dclarer une structure entire ou un tableau avec le mot cl register.
Qui plus est, les variables places dans des registres sont forcment locales des
fonctions ; on ne peut pas dfinir une variable globale en tant que registre.
Aujourd'hui, ce mot-cl est dconseill sauf pour des cas particuliers, les compilateurs
modernes sachant gnralement mieux que le programmeur comment optimiser et quelles
variables placer dans les registres.
#include
intmain(void)
{
registershort i, j;
for (i =1; i
8/6/2019 programmation_C
29/123
Classe de stockage 29
}
Classe 'auto'
Cette classe est un hritage du langage B. En C, ce mot-cl sert pour les variables locales
une fonction non-statiques, dites aussi automatiques. Mais une variable dclare
localement une fonction sans qualificateur static tant implicitement automatique, cemot-cl est inutile en C.
QualificateursLe C dfinit trois qualificateurs pouvant influer sur une variable :
const : pour dfinir une variable dont la valeur ne devrait jamais changer ;
restrict : permet une optimisation pour la gestion des pointeurs ;
volatile : dsigne une variable pouvant tre modifie notamment par une source
externe indpendante du programme.
Une variable, ou un paramtre de fonction, peut avoir aucun, un, deux, ou les troisqualificateurs (certaines combinaisons n'auraient que peu de sens, mais sont autorises).
Qualificateur 'const'
La classe const ne dclare pas une vraie constante, mais indique au compilateur que la
valeur de la variable ne doit pas changer. Il est donc impratif d'assigner une valeur la
dclaration de la variable, sans quoi toute tentative de modification ultrieure entrainera
une erreur de la part du compilateur :
Ce code contient une erreur volontaire !
constint i =0;i =1; /* erreur*/
En fait, le mot-cl const est beaucoup plus utilis avec des pointeurs. Pour indiquer qu'on
ne modifie pas l'objet point, il est bon de spcificier le mot-cl const :
voidfonction( constchar* pointeur )
{
pointeur[0] =0; /* erreur*/
pointeur ="Nouvelle chaine de caractres";
}
Dans cet exemple, on indique que l'objet point ne sera pas modifi. Pour indiquer que la
valeur elle-mme du pointeur est constante, il faut dclarer la variable de la sorte :
Ce code contient une erreur volontaire !
char*const pointeur ="Salut tout le monde !";
pointeur ="Hello world !"; /* erreur*/
Encore plus subtil, on peut mlanger les deux :
Ce code contient plusieurs erreurs volontaires !
constchar*const pointeur ="Salut tout le monde !";
pointeur ="Hello world !"; /* erreur*/
pointeur[0] =0; /* erreur*/
http://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svghttp://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svghttp://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svg8/6/2019 programmation_C
30/123
Classe de stockage 30
Cette dernire forme est nanmoins rarement usite. En outre ce dernier exemple prsente
un autre problme qui est la modification d'une chaine de caractres en dur , qui sont la
plupart du temps places dans la section lecture seule du programme et donc inaltrables.
Qualificateur 'volatile'
Ce mot-cl sert spcifier au compilateur que la variable peut tre modifie son insu.Cela annule toute optimisation que le compilateur pourrait faire, et l'oblige procder
chaque lecture ou criture dans une telle variable tel que le programmeur l'a crit dans le
code. Ceci a de multiples utilisations :
pour les coordonnes d'un pointeur de souris qui seraient modifies par un autre
programme ;
pour la gestion des signaux (voir Gestion des signaux) ;
pour de la programmation avec de multiples fils d'excution qui doivent communiquer
entre eux ;
pour dsigner des registres matriels qui peuvent tre accds depuis un programme C
(une horloge, par exemple), mais dont la valeur peut changer indpendamment duprogramme ;
etc.
On peut combiner const et volatile dans certaines situations. Par exemple :
extern const volatile int horloge_temps_reel;
dclare une variable entire, qu'on ne peut modifier partir du programme, mais dont la
valeur peut changer quand mme. Elle pourrait dsigner une valeur incrmente
rgulirement par une horloge interne.
Qualificateur 'restrict'Introduit par C99, ce mot-cl s'applique aux dclarations de pointeurs uniquement. Avec
restrict, le programmeur certifie au compilateur que le pointeur dclar sera le seul
pointer sur une zone mmoire. Cela permettra au compilateur d'effectuer des optimisations
qu'il n'aurait pas pu devinerautrement. Le programmeur ne doit pas mentirsous peine de
problmes...
Par exemple :
int* restrict pZone;
8/6/2019 programmation_C
31/123
Oprateurs 31
Oprateurs
Les oprateurs du CLes oprateurs du C permettent de former des expressions, expressions qui diront quoi
faire votre programme. On peut voir un programme C comme tant compos de troiscatgories d'instructions :
Les dclarations et dfinitions (variables, fonctions, types) : dclarent et dfinissent
les objets que pourront manipuler le programme.
Les expressions : manipulent les dclarations, via les oprateurs.
Les instructions : manipulent les expressions pour leur donner une signification
particulire (test, boucle, saut, ...).
Les dclarations de variables ont en partie t dcrites dans les chapitres prcdents. Les
expressions seront en partie dcrites dans celui-ci (les oprateurs lis aux pointeurs,
tableaux, structures et fonctions seront dcrit dans des chapitres ddis), et les instructions
seront dcrites au cours des chapitres suivants.
Les expressions en C sont en fait trs gnriques, elles peuvent inclure des oprations
arithmtiques classiques (addition, soustraction, division, modulo, ...), des expressions
boolennes (OU logique, ET logique, OU exclusif, ...), des comparaisons (galit, ingalit,
diffrence, ...) et mme des affectations (copie, auto-incrment, ...). Toutes ces oprations
peuvent s'effectuer en une seule expression, il suffit d'appliquer les bons oprateurs sur les
bons oprandes.
Les oprateurs binaires et ternaires utilisent une notation infixe (l'oprateur se trouve
entre les 2 ou 3 oprandes). Les oprateurs unaires s'crivent de manire prfix (avant
l'oprande), l'exception des oprateurs ++ et -- qui peuvent s'crire de manire prfixeou postfixe (avec une diffrence subtile, dcrite ci-aprs).
La priorit (quel oprateur est appliqu avant, en l'absence de parenthses explicite) et
l'associativit (dans quel ordre sont traits les arguments des oprateurs ayant la mme
priorit) sont rsumes dans la table suivante (par ordre dcroissant de priorit - les
oprateurs dcrits dans un autre chapitre ont un lien ddi) :
oprateur arit associativit description
( ) gauche vers la droite
(GD)
parenthsage
() [] .-> GD appel de fonction, index de tableau, membrede structure, pointe sur membre de structure
! unaire droite vers la gauche
(DG)
ngation boolenne
~ unaire DG ngation binaire
++ -- unaire DG incrmentation et dcrmentation
- unaire DG oppos
(type) unaire DG oprateur de transtypage (cast)
* unaire DG oprateur de drfrenage
& unaire DG oprateur de rfrenage
http://fr.wikibooks.org/w/index.php?title=Programmation_C_Pointeurs%23Usage_et_d.C3.A9clarationhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Pointeurs%23D%C3%A9r%C3%A9f%C3%A9rencementhttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Pointeurs_vers_structureshttp://fr.wikibooks.org/w/index.php?title=Programmation_C_Types_avanc%C3%A9s%23Acc.C3.A8s_aux_champs8/6/2019 programmation_C
32/123
Oprateurs 32
sizeof unaire DG fournit la taille en nombre de "char" de
l'expression (souvent en octet mais pas
toujours, mais sizeof(char) == 1 par
dfinition, voir Caractres)
* / % binaire GD multiplication, division, modulo (reste de la
division)
+ - binaire GD addition, soustraction
>> >= < >=
8/6/2019 programmation_C
33/123
Oprateurs 33
mme compilateur :
Ce code contient plusieurs erreurs volontaires !
/* Le code qui suit est imprvisible */
i = i++;
/* Ou de faon moins vidente */j = f(++i, 22, i);
Promotion entire
La promotion entire, ne pas confondre avec la conversion automatique de type, fait que
tous les types plus petits ou gaux int (char, short, champs de bits, type numr) sont
convertis (promus) en int ou unsigned avant toute opration. Ainsi, dans l'exemple
suivant, a + b est calcul avec des int et le rsultat est de type int :
shortsum(short a, short b) {
return a + b; /* quivaut : return (int)a + (int)b; */}
Le compilateur peut mettre un avertissement du fait que le rsultat int est converti en
short pour tre retourn, et cette conversion peut causer une perte de prcision (par
exemple si int a une largeur de 32 bits et short de 16 bits).
La promotion se fait vers unsigned lorsqu'un int ne peut pas reprsenter le type promu.
Conversion automatique
La conversion est un mcanisme qui permet de convertir implicitement les nombres dans le
format le plus grand utilis dans l'expression.L'exemple classique est le mlange des nombres rels avec des nombres entiers. Par
exemple l'expression '2 / 3.' est de type double et vaudra effectivement deux tiers
(0,666666...). L'expression '2 * a / 3' calculera les deux tiers de la variable 'a', et
arrondira automatiquement l'entier par dfaut, les calculs ne faisant intervenir que des
instructions sur les entiers (en supposant que 'a' soit un entier). noter que l'expression '2
/ 3 * a' vaudra... toujours zro !
Plus subtile, l'expression '2 * a / 3.', en supposant toujours que a soit un entier,
effectuera une multiplication entire entre 2 et a, puis promouvra le rsultat en rel
(double) puis effectuera la division relle avec trois, pour obtenir un rsultat rel lui-aussi.
Enfin un cas o les promotions peuvent surprendre, c'est lorsqu'on mlange des entiers
signs et non-signs, plus particulirement dans les comparaisons. Considrez le code
suivant :
/* Ce code contient un effet de bord sibyllin */
unsignedlong a =23;
signedchar b =-23;
printf( "a %c b\n", a < b ?'') );
De toute vidence a est suprieur b dans cet exemple. Et pourtant, si ce code est excutsur certaines architectures, il affichera a < b, justement cause de cette conversion.
http://fr.wikibooks.org/w/index.php?title=Fichier:Achtung.svg8/6/2019 programmation_C
34/123
Oprateurs 34
Tout d'abord dans la comparaison a < b, le type de a est le plus grand , donc b est
promu en unsigned long. C'est en fait a le problme : -23 est une valeur ngative, et la
conversion d'une valeur ngative en un type non sign se fait modulo la valeur maximale
reprsentable par le type non sign + 1. Si la valeur maximale pour le type unsigned long
est 232-1, alors -23 est converti modulo 232, et devient 4294967273 (soit 232-23). Dans ce
cas l effectivement 23 < 4294967273, d'o ce rsultat surprenant.
noter qu'on aurait eu le mme problme si le type de b tait signed long. En fait les
types signs sont promus en non-signs, s'il y a au moins une variable non-signes dans
l'expression, et que le type non-sign est "plus grand" que le type sign.
Dans ce cas prsent, il faut effectuer soi-mme le transtypage :
printf( "a %c b\n", (long) a < b ?'') );
La norme dfinit prcisment les conversions arithmtiques et les promotions entires, se
rfrer elle pour les dtails.
valuation des expressions boolennesLe C ne possde pas de type boolen ddi[1] . Dans ce langage, n'importe quelle valeur
diffrente de zro est considre vraie, zro tant considr comme faux. Ce qui veut dire
que n'importe quelle expression peut tre utilise l'intrieur des tests (entier, rels,
pointeurs, tableaux, etc.). Cela peut conduire des expressions pas toujours trs claires,
comme :
int a;
a = une_fonction();
if (a)
{ /* ... */
}
Ce type d'criture simplifie a ses adeptes, mais elle peut aussi s'crire de la manire
suivante:
int a;
a = une_fonction();
if (a !=0)
{
/* ... */}
Cette seconde criture, smantiquement quivalente la premire, rend explicite le test
qui est effectu (on compare la valeur de la variable a zro).
Par ailleurs, cette absence de type boolen rend aussi valide le code suivant:
int a =0;
int b =2;
if (a = b)
{ /* Le code qui suit sera toujours excut ... */
8/6/2019 programmation_C
35/123
Oprateurs 35
}
Dans cet exemple, il y a un seul caractre = entre a et b, donc on ne teste pas si a est gal
b, mais on affecte la valeur de la variable b la variable a. Le rsultat de l'expression
tant 2, elle est donc toujours considre vraie. Ce genre de raccourci est en gnral
viter. En effet, il est facile de faire une faute de frappe et d'oublier de taper un caratre =.
Comme le code rsultant est toujours valide au sens du C, cette erreur peut ne pas tre vueimmdiatement. Pour aider les dveloppeurs dtecter ce genre d'erreurs, de nombreux
compilateurs mettent un avertissement quand un tel code leur est prsent. Une manire
de faire taire ces avertissements, une fois qu'on s'est assur qu'il ne s'agit pas d'une erreur,
est de parenthser l'affectation:
/* On veut faire une affectation ici. */
/* double parenthsage pour supprimer l'avertissement du compilateur*/
if ((a = b))
{
/* ... */}
Comme un dveloppeur devant maintenir un programme contenant un test if (a = b) {
/* ... */ } se demandera si le dveloppeur prcdent n'a pas fait une faute de frappe, il
est prfrable d'viter autant que possible ce genre de situations et, s'il est ncessaire (ce
qui a trs peu de chances d'arriver), de la commenter. En effet, mme un code if ((a =
b)) { /* ... */ } non comment doit tre lu avec attention, car le dveloppeur
prcdent peut avoir ajout les parenthses juste pour faire taire le compilateur, sans se
rendre compte d'une erreur. Dans tous les cas, la manire la plus sre est de dcomposer
ainsi:
a = b;
if (a !=0)
{
/* ... *