Programmation C
Programmation C/Bases du langage
Un programme C dans son ensemble peut être décrit comme un ensemble de fonctions qui s'appellent les unes les autres. Une fonction parmi celles-ci est obligatoire : la fonction codice_1 ; C'est celle-ci qui est appelée par le système d'exploitation lorsque vous lui demandez d'amorcer votre programme. La notion de fonction en elle-même est un concept assez avancé, et sera expliquée plus loin dans le cours. Pour l'instant, abordez la notion de manière intuitive.
Bonjour !
L'un des plus petits programmes possible en langage C est :
int main(void)
 printf("Bonjour !\n");
 return 0;
"(Les numéros de lignes ont été ajoutés pour la lisibilité, mais ne font pas partie du programme.)"
Ce programme a pour seul but d'afficher le texte « Bonjour ! » suivi d'un retour à la ligne. 
Voici la description de chaque ligne qui le compose :
Inclusion de l'en-tête nommé codice_2. Il est lié à la gestion des entrées et sorties ("STanDard Input Output", entrées/sorties standards) et contient, entre autres, la déclaration de la fonction codice_3 permettant d'afficher du texte formaté.
int main(void)
Définition de la fonction principale du programme, codice_1 ("principal" en anglais). Il s'agit de la fonction appelée au démarrage du programme, tout programme en C doit donc la définir. La partie entre parenthèses spécifie les paramètres que reçoit le programme : ici, le programme n'utilisera aucun paramètre, ce qui est spécifié en C avec le mot-clé codice_5 ("vide"). La partie à gauche du nom de la fonction codice_1 spécifie le type renvoyé par la fonction : la fonction codice_1 est définie par la norme C comme renvoyant une valeur entière, de type codice_8 (pour "integer", entier), au système d'exploitation.
Début de la définition de la fonction codice_1.
 printf("Bonjour !\n");
Appel de la fonction codice_3 ("print formatted", affichage formaté, qui sera expliquée dans le chapitre dédié à cette fonction). La chaîne « Bonjour ! » va être affichée, elle sera suivie d'un retour à la ligne, représenté en C par codice_11.
 return 0;
La fonction codice_1 a été définie comme retournant ("to return") une valeur de type codice_8, on renvoie donc une telle valeur. Par convention, la valeur 0 indique au système d'exploitation que le programme s'est terminé normalement.
Fin de la définition de la fonction codice_1.
Ce premier exemple ne détaille évidemment pas tout ce qui concerne la fonction codice_1, ou codice_3, par exemple. La suite de l'ouvrage précisera les points nécessaires dans les chapitres appropriés (voir par exemple le paragraphe "la fonction main" du chapitre "Fonctions et procédures", ou le paragraphe "Sorties formatées" du chapitre "Entrées/sorties").
Compilation.
Pour exécuter un programme C, il faut préalablement le .
Tapez le code source du programme "Bonjour !" dans un et sauvegardez-le sous le nom codice_17 (l'extension codice_18 n'est pas obligatoire, mais est usuelle pour un fichier source en C). Ouvrez une fenêtre de commandes (terminal sous Unix, commandes MS-DOS sous Windows), et placez-vous dans le répertoire où est sauvegardé votre fichier. Pour compiler avec le compilateur standard de votre système, il faut taper la commande : 
D'autres compilateurs pour le langage C peuvent être utilisés.
La compilation du programme produira un fichier exécutable, appelé codice_19 sous Unix, et codice_20 sous Windows. Il peut être exécuté en tapant codice_21 sous Unix, et codice_22 sous Windows.
Éléments de syntaxe.
Identificateurs.
Les s commencent par une lettre ou le caractère souligné ("_") et peuvent contenir des lettres, des chiffres et le caractère souligné (cependant, les identificateurs commençant par deux caractères soulignés, ou un caractère souligné suivi d'une majuscule sont réservés par l'implémentation, et ne doivent pas être utilisés dans un programme « ordinaire »). Tous les mots-clés ainsi que les symboles (variables, fonctions, champs, etc.) sont sensibles à la casse des lettres. Quelques exemples d'identificateurs valides :
toto
_coin_coin76
Mots réservés du langage.
Le langage, dans la norme C90, possède 32 mots réservés (ou mots-clés) qui ne peuvent pas être utilisés comme identificateurs. La norme C99 en a ajouté cinq ; la norme C11 en a de nouveau apporté 7. Le tableau ci-dessous les liste tous, avec la mention "« C99 »" ou "« C11 »" pour indiquer ceux définis uniquement dans les versions correspondantes ou ultérieures :
Un programme C90 peut par exemple définir codice_23 comme un identifiant de variable ou de fonction mais cela est très déconseillé, car il sera invalide au sens de la norme C99. Une mise à jour du compilateur peut alors l'empêcher de compiler le code source en question. Pour éviter de telles situations, il est préférable de considérer "tous" les mots-clés du tableau précédent comme étant réservés, quels que soient le compilateur et la norme utilisés.
Commentaires.
Les commentaires commencent par codice_24 et se terminent par codice_25, ils ne peuvent pas être imbriquées :
/* ceci est un commentaire */
 ceci est aussi un commentaire
/* /* ceci est encore un commentaire */
/* /* */ ceci n’est pas un commentaire */
Inclure des commentaires pertinents dans un programme est un art subtil. Cela nécessite un peu de pratique pour savoir guider les lecteurs et attirer leur attention sur certaines parties délicates du code. Pour faire court, on ne saurait trop que rappeler ce célèbre vers de Nicolas Boileau, qui disait que « ce que l'on conçoit bien, s'énonce clairement et les mots pour le dire arrivent aisément » (Art Poétique, 1674). Ou encore, pour adopter une approche plus pragmatique : si un programmeur a du mal à commenter (expliquer, "spécifier") le fonctionnement d'un passage de code, c'est que le code est mal conçu et qu'il serait bénéfique de le réécrire plus lisiblement.
Attention! Les commentaires ne devraient pas être employés pour désactiver 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 préprocesseur dispose d'instructions dédiées, qui permettent heureusement de désactiver du code en laissant les commentaires.
Le codice_26 ajoute la possibilité de placer un commentaire d'une seule ligne, à partir du codice_26 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 (codice_28), on peut placer autant d'instructions que l'on veut sur une même ligne (même si ce n'est pas conseillé pour la lisibilité du code). Les "blocs d'instructions" commencent par une accolade ouvrante (codice_29) et se terminent par une accolade fermante (codice_30). Les instructions doivent obligatoirement être déclarées 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 même ligne */
i = 1; j = 2; printf("bonjour\n");
/* un bloc */
 int i;
 i = 5;
/* l'instruction vide */
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 religions concernant les styles d'indentation, mais pour faire court et éviter les guerres saintes, on ne saurait trop conseiller que d'utiliser le même nombre de blancs par niveau d'imbrication de bloc.
À noter que l'instruction vide étant valide en C, on peut donc pratiquement rajouter autant de point-virgules que l'on veut. Le point-virgule ne sert pas uniquement à marquer la fin des instructions, les compilateurs l'utilisent généralement comme caractère de synchronisation, suite à une erreur dans un programme source. En fait, en général, lorsqu'une erreur est détectée, les compilateurs ignorent tout jusqu'au prochain point-virgule. Ce qui peut avoir des conséquences assez dramatiques, comme dans l'exemple suivant :
int traite_arguments(int nb, char * argv[])
 /* ... */
 return 0
int main(int nb, char * argv[])
 int retour;
 retour = traite_arguments(nb, argv);
On notera l'absence de point-virgule à la fin de l'instruction codice_31 à la fin de la fonction codice_32. Ce que la plupart des compilateurs feront dans ce cas sera d'ignorer tout jusqu'au prochain point-virgule. On se rend compte du problème : on a sauté une déclaration de fonction (avec ses deux paramètres) et une déclaration de variable. Ce qui veut dire qu'une cascade d'erreurs va suivre suite à l'oubli... d'un seul caractère (codice_28) !
Déclarations de variables.
T var1, var2, ..., varN;
Cette ligne déclare les variables "var1", "var2", ..., "varN" de type "T". Une variable est dite "locale", si elle est définie à l'intérieur d'une fonction et "globale" si définie en-dehors. 
Par exemple :
int jour; /* 'jour' est une variable globale, de type entier */
int main(void)
 double prix; /* 'prix' est une variable locale à la fonction 'main', de type réel */
 return 0;
Variables locales.
Les variables locales (aussi appelées "automatiques") ne sont visibles que dans le bloc dans lequel elles sont définies, et n'existent que durant ce bloc. Par exemple :
int fonction(int n)
 int i; /* i est visible dans toute la fonction */
 i = n + 1;
 { /* début 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 précédent accède à codice_34 depuis un bloc contenu dans le bloc où codice_34 a été défini, ce qui est normal. Puis il essaye d'accéder à la valeur de la variable codice_36 "en-dehors" du bloc où elle à été définie, ce qui est une erreur.
Les variables locales ne sont pas initialisées automatiquement et contiennent donc, après leur déclaration, une valeur aléatoire. Utiliser une telle valeur peut causer un comportement aléatoire 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 même valeur aussi bien qu'il peut afficher une valeur différente à chaque exécution :
int main(void)
 int n;
 printf("La variable n vaut %d\n", n);
 return 0;
Avant la normalisation ISO C99, les déclarations de variables locales devaient obligatoirement être placées juste au début d'un bloc et s'arrêtaient à la première instruction rencontrée. Si une déclaration est faite au-delà, une erreur sera retournée. Suivant la norme C99, les déclarations 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 codice_22 est définie après l'instruction codice_38 :
int ma_fonction(int n)
 puts("Bonjour !");
 int a; /* Valide en C99, invalide en C90 */
 /* autre chose... */
 return a;
Variables globales.
Une attention particulière doit être portée 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 déclarées, en les déclarants statiques.
Les variables globales sont initialisées avant que la fonction codice_1 s'exécute. Si le programmeur ne fournit pas de valeur initiale explicitement, chaque variable reçoit une valeur par défaut suivant son type :
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.
int jour_courant(void)
 /* retourne le n° du jour courant */
int jour = jour_courant(); /* ERREUR ! */
int main(void)
 /* ... */
 return 0;
Le code précédent ne pourra pas compiler, car on ne peut appeler directement codice_41 pour initialiser codice_42. Si vous avez besoin d'un tel comportement, une solution est de faire l’initialisation explicite dans codice_1 :
int jour_courant(void)
 /* retourne le n° du jour courant */
int jour; /* 'jour' est initialisé à 0 *avant* le début de 'main' */
int main(void)
 jour = jour_courant();
 return 0;
Traitements des ambiguïtés.
Le C utilise un mécanisme élégant pour lever des constructions syntaxiques en apparence ambiguës. L'analyse des mots (lexèmes, "token" en anglais) se fait systématiquement de la gauche vers la droite. Si plusieurs lexèmes peuvent correspondre à une certaine position, le plus grand aura priorité. Considérez l'expression valide suivante :
a+++b;
Ce genre de construction hautement illisible et absconse est bien évidemment à éviter, mais illustre parfaitement bien ce mécanisme. Dans cet exemple, le premier lexème trouvé est bien sûr l'identificateur 'codice_22' puis le compilateur a le choix entre l'opérateur unaire 'codice_45', ou l'opérateur binaire 'codice_46'. Le plus grand étant le premier, c'est celui-ci qui aura priorité. L'instruction se décompose donc en :
(a ++) + b;