Les premiers pas
La norme ANSI C originale (X3.159-1989) a été ratifiée en 1989 et publiée en 1990. Cette norme a été ratifiée en tant que norme ISO (ISO/IEC 9899:1990) plus tard en 1990. Il n'y avait aucune différence technique entre ces publications, bien que les sections de la norme ANSI aient été renumérotées et soient devenues des clauses de la norme ISO. La norme ANSI, mais pas la norme ISO, était également accompagnée d'un document de justification. Cette norme, sous ses deux formes, est communément connue sous le nom de C89, ou parfois C90, à partir des dates de ratification. Pour sélectionner cette norme dans GCC, utilisez l'une des options -ansi, -std=c90 ou -std=iso9899:1990 ; pour obtenir tous les diagnostics requis par la norme, vous devez également spécifier -pedantic (ou -pedantic-errors si vous souhaitez qu'il s'agisse d'erreurs plutôt que d'avertissements).
Des erreurs dans la norme ISO C de 1990 ont été corrigées dans deux rectificatifs techniques publiés en 1994 et 1996. GCC ne prend pas en charge la version non corrigée.
Un amendement à la norme de 1990 a été publié en 1995. Cet amendement a ajouté des digrammes et __STDC_VERSION__ au langage, mais concernait par ailleurs la bibliothèque. Cet amendement est communément appelé AMD1 ; la norme modifiée est parfois connue sous le nom de C94 ou C95. Pour sélectionner cette norme dans GCC, utilisez l'option -std=iso9899:199409 (avec, comme pour les autres versions de norme, -pedantic pour recevoir tous les diagnostics requis).
Une nouvelle édition de la norme ISO C a été publiée en 1999 sous le nom d'ISO/IEC 9899:1999, et est communément appelée C99. (Pendant son développement, les brouillons de cette version de norme étaient appelés C9X.) GCC prend en charge de manière quasi complète cette version de norme. Pour sélectionner cette norme, utilisez -std=c99 ou -std=iso9899:1999.
Les erreurs de la norme ISO C de 1999 ont été corrigées dans trois rectificatifs techniques publiés en 2001, 2004 et 2007. GCC ne prend pas en charge la version non corrigée.
Une quatrième version de la norme C, connue sous le nom de C11, a été publiée en 2011 sous la référence ISO/IEC 9899:2011. (Pendant le développement, les projets de cette version de la norme étaient appelés C1X.) GCC offre un support quasi complet pour cette norme, activé avec -std=c11 ou -std=iso9899:2011. Une version avec corrections intégrées a été préparée en 2017 et publiée en 2018 sous la référence ISO/IEC 9899:2018 ; elle est connue sous le nom de C17 et est prise en charge avec -std=c17 ou -std=iso9899:2017 ; les corrections sont également appliquées avec -std=c11, et la seule différence entre les options est la valeur de __STDC_VERSION__.
Une autre version de la norme C, connue sous le nom de C23, est en cours de développement et devrait être publiée en 2024 sous la référence ISO/IEC 9899:2024. (Pendant le développement, les brouillons de cette version de la norme étaient appelés C2X.) Une prise en charge expérimentale et incomplète de cette norme est activée avec -std=c23 ou -std=iso9899:2024.
Par défaut, GCC fournit certaines extensions du langage de programmation C qui, dans de rares cas, entrent en conflit avec la norme C. Voir Extensions à la famille de langages de programmation C. Certaines fonctionnalités qui font partie de la norme C99 sont acceptées comme extensions en mode C90, et certaines fonctionnalités qui font partie de la norme C11 sont acceptées comme extensions en modes C90 et C99. L'utilisation des options -std répertoriées ci-dessus désactive ces extensions lorsqu'elles entrent en conflit avec la version standard C sélectionnée. Vous pouvez également sélectionner explicitement une version étendue du langage C avec -std=gnu90 (pour C90 avec extensions GNU), -std=gnu99 (pour C99 avec extensions GNU) ou -std=gnu11 (pour C11 avec extensions GNU).
La valeur par défaut, si aucune option de dialecte du langage C n'est donnée, est -std=gnu17.
La norme ISO C définit (dans la clause 4) deux classes d'implémentations conformes. Une implémentation hébergée conforme prend en charge l'ensemble de la norme, y compris toutes les fonctionnalités de la bibliothèque ; une implémentation autonome conforme n'est requise que pour fournir certaines fonctionnalités de la bibliothèque : celles de <float.h>, <limits.h>, <stdarg.h> et <stddef.h> ; depuis AMD1, également ceux de <iso646.h> ; depuis C99, également ceux de <stdbool.h> et <stdint.h> ; et depuis C11, également ceux de <stdalign.h> et <stdnoreturn.h>. De plus, les types complexes, ajoutés dans C99, ne sont pas requis pour les implémentations autonomes.
La norme définit également deux environnements pour les programmes, un environnement autonome, requis pour toutes les implémentations et pouvant ne pas avoir de fonctionnalités de bibliothèque au-delà de celles requises pour les implémentations autonomes, où la gestion du démarrage et de la fin du programme est définie par l'implémentation; et un environnement hébergé, qui n'est pas requis, dans lequel toutes les fonctionnalités de la bibliothèque sont fournies et le démarrage s'effectue via une fonction int main (void) ou int main (int, char *[]). Un noyau de système d'exploitation est un exemple de programme exécuté dans un environnement autonome ; un programme utilisant les fonctionnalités d'un système d'exploitation est un exemple de programme exécuté dans un environnement hébergé.
Le GCC a pour objectif de pouvoir être utilisé comme une implémentation autonome conforme ou comme compilateur pour une implémentation hébergée conforme. Par défaut, il agit comme compilateur pour une implémentation hébergée, définissant __STDC_HOSTED__ à 1 et en supposant que lorsque les noms des fonctions ISO C sont utilisés, ils ont la sémantique définie dans la norme. Pour le faire agir comme une implémentation autonome conforme pour un environnement autonome, utilisez l'option -ffreestanding ; elle définit alors __STDC_HOSTED__ à 0 et ne fait pas d'hypothèses sur la signification des noms de fonctions de la bibliothèque standard, avec les exceptions notées ci-dessous. Pour construire un noyau de système d'exploitation, vous devrez peut-être toujours prendre vos propres dispositions pour la liaison et le démarrage.
Le GCC ne fournit pas les fonctionnalités de bibliothèque requises uniquement pour les implémentations hébergées, ni toutes les fonctionnalités requises par C99 des implémentations autonomes sur toutes les plateformes. Pour utiliser les fonctionnalités d'un environnement hébergé, vous devez les trouver ailleurs (par exemple, dans la bibliothèque glibc).
La plupart des routines de support du compilateur utilisées par GCC sont présentes dans libgcc, mais il existe quelques exceptions. Le GCC exige que l'environnement autonome fournisse memcpy, memmove, memset et memcmp. Contrairement aux normes couvrant memcpy, le GCC s'attend à ce que le cas d'un chevauchement exact de la source et de la destination fonctionne et n'appelle pas de comportement indéfini. Enfin, si __builtin_trap est utilisé et que la cible n'implémente pas le modèle trap, alors GCC émet un appel à abort.
Installation de GCC
Avant de commencer, assurez-vous que gcc est installé sur votre machine. Sur Linux, vous pouvez l'installer via votre gestionnaire de paquets. Par exemple, sur une distribution basée sur Debian :
sudo apt update sudo apt install build-essential |
Structure de base d'un programme C
Un programme C de base en utilisant le GNU C ressemble à ceci :
- #include <stdio.h>
-
- int main() {
- printf("Bonjour le monde!\n");
- return 0;
- }
Compilation avec GCC
Une fois le programme écrit dans un fichier (par exemple hello.c), vous pouvez le compiler avec gcc en utilisant la commande suivante :
gcc hello.c -o hello |
Ici, -o hello indique que l'exécutable résultant sera nommé hello.
Exécution du programme
Après la compilation, vous pouvez exécuter votre programme :
./hello |
Variables et types de données
Les types de base en C incluent les entiers (int), les réels (float), les caractères (char), et les doubles (double). Voici un exemple avec quelques variables :
- #include <stdio.h>
-
- int main() {
- int x = 10;
- float y = 3.14;
- char z = 'A';
-
- printf("x = %d, y = %.2f, z = %c\n", x, y, z);
- return 0;
- }
Structures conditionnelles
Le C supporte les structures de contrôle classiques comme if, else, et switch :
Les boucles
Les boucles en C incluent les boucles for, while, et do-while :
- #include <stdio.h>
-
- int main() {
- for (int i = 0; i < 5; i++) {
- printf("i = %d\n", i);
- }
- return 0;
- }
Les fonctions
Le C permet de définir des fonctions pour organiser le code :
- #include <stdio.h>
-
- void greet() {
- printf("Bonjour de la fonction !\n");
- }
-
- int main() {
- greet(); // Appel de la fonction
- return 0;
- }
Gestion de la mémoire avec malloc et free
En C, vous gérez la mémoire manuellement avec malloc pour allouer de la mémoire dynamique et free pour la libérer :
- #include <stdio.h>
- #include <stdlib.h>
-
- int main() {
- int *ptr = (int *)malloc(sizeof(int)); // Allocation dynamique de mémoire
- if (ptr == NULL) {
- printf("Échec d'allocation de mémoire\n");
- return 1;
- }
-
- *ptr = 100; // Assignation d'une valeur
- printf("Valeur = %d\n", *ptr);
-
- free(ptr); // Libération de la mémoire
- return 0;
- }
Débogage avec gdb
Vous pouvez utiliser le débogueur GNU (gdb) pour examiner le comportement de votre programme.
Compilez votre programme avec l'option -g pour inclure les symboles de débogage :
gcc -g hello.c -o hello |
Démarrez gdb
gdb ./hello |
Cela vous permet de définir des points d'arrêt, inspecter des variables,...