Menu

Comment compiler et exécuter un programme C (gcc, pas à pas)

Transformer un fichier .c en programme qui tourne : la commande gcc, ce que font réellement le préprocesseur, le compilateur et l'éditeur de liens, les options à utiliser dès le premier jour, et comment lire les erreurs quand cela échoue.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Le C est un langage compilé : rien ne s'exécute tant qu'un compilateur n'a pas traduit votre source en code machine pour votre processeur et votre système d'exploitation précis. Cette étape tient en une commande, mais savoir ce qu'elle fait rend la plupart des messages d'erreur évidents au lieu de mystérieux.

Les deux commandes

Enregistrez ceci sous hello.c :

#include <stdio.h>

int main(void) {
    printf("Bonjour, C !\n");
    return 0;
}

Puis, dans le même dossier :

gcc hello.c -o hello
./hello

La première commande compile. La seconde exécute le résultat. Sous Windows, la commande d'exécution est hello dans l'invite de commandes ou .\hello dans PowerShell - il n'y a pas de préfixe ./, car Windows cherche dans le répertoire courant par défaut et les shells Unix, délibérément, non.

Si vous omettez -o hello, gcc nomme la sortie a.out (ou a.exe), d'où les vieux tutoriels qui finissent par ./a.out. Nommez toujours votre sortie ; cela coûte quatre caractères et évite la confusion.

Voici le même programme dans l'éditeur du navigateur, qui fait les deux étapes pour vous :

Ce que « compiler » fait réellement

gcc hello.c -o hello ressemble à une étape. Il y en a quatre, et chacune peut échouer avec son propre type d'erreur.

1. Le prétraitement. Avant qu'aucun C ne soit compilé, le préprocesseur traite chaque ligne commençant par #. #include <stdio.h> est littéralement remplacé par le contenu de ce fichier d'en-tête ; les macros #define sont développées ; les blocs #ifdef sont gardés ou supprimés. Le résultat est un gros fichier C sans plus aucune ligne #. Vous pouvez le voir :

gcc -E hello.c

Cela affiche des centaines de lignes - presque tout est stdio.h collé sur place.

2. La compilation. Le C prétraité est analysé, vérifié au niveau des types et traduit en assembleur pour votre processeur. C'est de là que viennent les erreurs de syntaxe, les erreurs de type et les avertissements.

3. L'assemblage. L'assembleur devient un fichier objet - du code machine avec des trous là où vont les appels aux fonctions d'autres fichiers.

gcc -c hello.c   # produit hello.o, s'arrete avant l'edition de liens

4. L'édition de liens. Les fichiers objets sont recousus avec la bibliothèque standard C, chaque trou est rempli d'une vraie adresse, et le résultat est un exécutable. C'est de là que viennent les erreurs « undefined reference ».

Ce qu'il faut en retenir en pratique : une erreur de compilation pointe une ligne de votre source, une erreur d'édition de liens non, car l'édition de liens intervient après que chaque ligne a déjà été acceptée.

Les options à utiliser dès le premier jour

Le simple gcc file.c -o prog accepte silencieusement beaucoup de code dangereux. Quatre options changent cela.

gcc -std=c17 -Wall -Wextra -g hello.c -o hello
  • -Wall active les avertissements courants. Malgré son nom, ce n'est pas « tous » les avertissements - c'est l'ensemble raisonnable.
  • -Wextra en ajoute d'autres, dont les paramètres inutilisés et certaines erreurs de comparaison.
  • -std=c17 fixe le standard du langage pour que votre code signifie la même chose sur toutes les machines. Utilisez -std=c99 si vous suivez des supports plus anciens.
  • -g conserve les informations de débogage, pour que gdb ou lldb puisse montrer vos vraies lignes de source en cas de plantage.

Deux autres dont vous aurez besoin plus tard :

  • -O2 active l'optimisation pour les versions de production. Laissez-la de côté pendant l'apprentissage : le code optimisé est plus difficile à déboguer, et les avertissements bougent parfois.
  • -fsanitize=address,undefined (gcc et clang) fait abandonner le programme avec un message clair dès qu'il lit hors bornes ou tombe sur un comportement indéfini. C'est l'option d'apprentissage la plus utile du C.

Essayez les avertissements par vous-même. Ce programme compile et s'exécute, mais il a deux vrais bugs :

count ne reçoit jamais de valeur, donc le programme affiche les octets qui se trouvaient là. Avec -Wall, le compilateur le dit : 'count' is used uninitialized. Les avertissements en C ne sont presque jamais du bruit - traitez-les comme des erreurs que vous n'avez pas encore rencontrées.

Compiler plus d'un fichier

Les vrais programmes sont répartis sur plusieurs fichiers. Passez-les tous à gcc :

gcc -std=c17 -Wall main.c utils.c -o myprog

Ou compilez chacun séparément et liez à la fin, ce que font les systèmes de construction pour que changer un fichier ne reconstruise pas tout :

gcc -c main.c      # -> main.o
gcc -c utils.c     # -> utils.o
gcc main.o utils.o -o myprog

Certaines bibliothèques demandent une option de liaison explicite. La bibliothèque mathématique est celle que tout débutant rencontre :

gcc calc.c -o calc -lm

Sans -lm, utiliser sqrt de math.h compile très bien puis échoue à l'édition de liens avec undefined reference to sqrt - la déclaration était dans l'en-tête, mais le code était dans une bibliothèque que personne n'a demandée.

Lire les erreurs

Les erreurs du C sont laconiques mais cohérentes. Trois exemples couvrent l'essentiel de ce que vous verrez au début.

Un point-virgule manquant est signalé sur la ligne suivante, parce que le compilateur a continué à lire :

hello.c:5:5: error: expected ';' before 'return'

La correction appartient à la ligne 4, pas à la 5. Chaque fois qu'une erreur pointe une ligne qui semble correcte, vérifiez celle d'avant.

Un en-tête manquant ressemble à un mystère sur une fonction que vous avez manifestement bien orthographiée :

hello.c:4:5: warning: implicit declaration of function 'printf'

Cela signifie que le compilateur n'a jamais vu de déclaration de printf : vous avez oublié #include <stdio.h>. En C99 et après, c'est une erreur, pas seulement un avertissement.

Un échec d'édition de liens n'a aucun numéro de ligne :

/usr/bin/ld: main.o: in function `main':
main.c:(.text+0x1a): undefined reference to `helper'

Le compilateur vous a cru quand vous disiez que helper existe quelque part ; l'éditeur de liens a cherché et il n'existe pas. Soit vous n'avez jamais écrit la définition, soit vous l'avez orthographiée autrement, soit vous avez oublié de passer à gcc le fichier qui la contient.

Corrigez toujours la première erreur. Les erreurs du C font cascade - une mauvaise ligne peut générer vingt messages, et dix-neuf disparaissent quand la première est corrigée.

Codes de sortie

return 0 dans main n'est pas décoratif. C'est le code de sortie du programme, et le shell peut le lire :

Après exécution, echo $? sur macOS/Linux (ou echo %errorlevel% sous Windows) affiche ce nombre. Les scripts et les outils de construction s'en servent pour décider s'il faut continuer. La convention est absolue : 0 est le succès, et le non-nul est un code d'erreur de votre choix. stdlib.h définit EXIT_SUCCESS et EXIT_FAILURE si vous préférez les noms.

Depuis C99, tomber au bout de main sans return est traité comme return 0 - mais l'écrire est plus clair, et c'est obligatoire pour toutes les autres fonctions.

Questions fréquentes

Comment compiler et exécuter un programme C ?

Enregistrez le code sous hello.c, puis lancez gcc hello.c -o hello pour le construire et ./hello pour l'exécuter (juste hello sous Windows). Si gcc est introuvable, vous devez d'abord installer un compilateur.

Que fait gcc -o ?

-o nomme le fichier de sortie. gcc hello.c -o hello produit un exécutable appelé hello. Sans -o, gcc écrit dans a.out (ou a.exe sous Windows), ce qui explique que tant de vieux tutoriels lancent ./a.out.

Quelles options gcc faut-il toujours utiliser ?

gcc -std=c17 -Wall -Wextra -g votrefichier.c -o votreprog. -Wall -Wextra activent les avertissements qui attrapent de vrais bugs, -std=c17 fixe la version du langage, et -g conserve les symboles de débogage pour qu'un débogueur puisse montrer votre source. Ajoutez -O2 quand vous voulez de la vitesse dans une version de production.

Que signifie « undefined reference to » en C ?

C'est une erreur de l'éditeur de liens : le compilateur a accepté l'appel d'une fonction, mais aucune définition de cette fonction n'a été trouvée. Les causes courantes sont une faute de frappe dans le nom, l'oubli de compiler un second fichier .c, ou l'usage d'une fonction mathématique sans lier la bibliothèque mathématique (-lm).

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER