argc et argv en C : lire les arguments

Comprends argc et argv en C, les indices valides, argv[argc] à NULL et la vérification à faire avant de lire un argument.

Par
Publié le

Tu lances ./sum 3 7, puis tu vois argc et argv dans le prototype de main. Le premier compte les entrées reçues. Le second donne leurs chaînes, dans l'ordre où le programme les reçoit.

En bref

En C, argc est le nombre de pointeurs utilisables dans argv. Quand argc vaut 3, les indices valides vont de 0 à 2, et argv[3] vaut NULL. Sur un lancement ordinaire par le shell, argv[0] désigne le programme et le premier argument fourni est argv[1], donc vérifie argc avant de lire cet indice.

Que contiennent argc et argv avec ./programme rouge "deux mots" ?

Le shell découpe la commande avant le démarrage du programme. Les espaces séparent les arguments, sauf dans les guillemets : "deux mots" arrive donc dans une seule chaîne. Ce programme affiche la structure reçue et parcourt argv jusqu'au pointeur nul final.

argv-layout.cVisualiser
#include <stdio.h>
int main(int argc, char *argv[]){    int i;
    printf("argc=%d\n", argc);    i = 0;    while (argv[i] != NULL) {        printf("argv[%d]=%s\n", i, argv[i]);        i++;    }    printf("argv[%d]=NULL\n", i);    return 0;}
Terminal
$ gcc -std=c17 -Wall -Wextra -Werror argv-layout.c -o argv-layout$ ./argv-layout red "two words"argc=3argv[0]=./argv-layoutargv[1]=redargv[2]=two wordsargv[3]=NULL$ ./argv-layoutargc=1argv[0]=./argv-layoutargv[1]=NULL

Les trois pointeurs comptés sont argv[0], argv[1] et argv[2]. argv[3] n'est pas un argument, c'est la sentinelle demandée par le langage. Elle rend possible une boucle qui s'arrête sur NULL, mais argc reste plus pratique quand ton programme exige un nombre précis d'arguments.

  1. ./sum 3 7la commande écrite dans le shell
  2. argc = 3trois pointeurs avant la sentinelle
  3. argv[0..2]./sum, 3, 7
  4. argv[3] = NULLla borne après le dernier argument
De la commande aux chaînes que main reçoit

Pourquoi argv[1] plante-t-il parfois ?

argv[1] n'existe comme chaîne que si argc est au moins 2. Sans argument utilisateur, le lancement courant donne argc == 1 et argv[1] == NULL. Donner ce pointeur à printf avec %s, à strcmp ou à strtol ne valide rien : ces fonctions attendent une chaîne qui existe.

Teste le compte avant toute lecture. Cet exemple accepte exactement un mot et affiche une aide sinon. Le repli sur "program" évite aussi de transmettre un pointeur nul à %s sur une implémentation qui appelle main avec argc == 0.

argv-exact.cVisualiser
#include <stdio.h>
int main(int argc, char *argv[]){    const char *name;
    name = argc > 0 ? argv[0] : "program";    if (argc != 2) {        fprintf(stderr, "usage: %s WORD\n", name);        return 2;    }    printf("word=%s\n", argv[1]);    return 0;}
Terminal
$ gcc -std=c17 -Wall -Wextra -Werror argv-exact.c -o argv-exact$ ./argv-exact helloword=hello$ ./argv-exact; echo status=$?usage: ./argv-exact WORDstatus=2$ ./argv-exact hello extra; echo status=$?usage: ./argv-exact WORDstatus=2
Lit argv[1] sans borneÀ éviter
printf("%s\n", argv[1]);
Vérifie la forme de la commandeCorrect
if (argc != 2)    return 2;printf("%s\n", argv[1]);

Est-ce que argv[0] est toujours le nom du programme ?

Le standard dit que si argc est supérieur à zéro, argv[0] représente le nom du programme. Sa forme dépend de l'environnement : tu peux recevoir ./sum, un chemin complet ou une chaîne vide si ce nom n'est pas disponible. Ne t'en sers pas pour retrouver un fichier ou décider d'une option métier.

Sur Linux, execve reçoit lui aussi un tableau d'arguments terminé par NULL. Celui qui lance le processus choisit son premier élément, ce qui explique pourquoi le contenu de argv[0] n'est pas une identité fiable du binaire.

Quand utiliser argc, et quand parcourir argv jusqu'à NULL ?

Utilise argc pour une forme attendue, par exemple argc != 2 pour un seul argument utilisateur. Utilise une boucle sur les indices de 1 à argc - 1 quand le programme accepte un nombre variable d'arguments. La boucle sur argv[i] != NULL est correcte aussi, mais elle inclut naturellement argv[0] si tu pars de zéro.

Pour transformer les chaînes "3" et "7" en nombres, ne les additionne pas directement : elles restent des caractères. L'article Lire un argument entier avec strtol montre comment contrôler toute la conversion.

C

arg_count

Écris un programme qui affiche le nombre d'arguments fournis après le nom de l'exécutable. Tu dois distinguer argc du nombre d'arguments utilisateur.

Ouvrir l'exercice

Questions fréquentes

argc compte-t-il le nom du programme ?

Lors d'un lancement habituel, oui. ./outil bleu vert donne argc == 3 : le programme à l'indice 0, puis bleu et vert.

Pourquoi argv a-t-il une case NULL après le dernier argument ?

La norme l'impose comme sentinelle. Une fonction peut donc parcourir le tableau sans recevoir argc, à condition de s'arrêter avant de déréférencer ce pointeur nul.

Puis-je modifier argv ?

Oui, les paramètres argc, argv et les chaînes pointées par argv sont modifiables dans l'environnement hébergé décrit par la norme. Évite de le faire pour analyser des options : garde les entrées intactes ou copie ce que tu veux transformer.

Pourquoi argc peut-il valoir 0 ?

Le C hébergé exige seulement une valeur non négative. Le shell que tu utilises donnera presque toujours au moins le programme, mais le test argc > 0 est simple quand tu dois afficher argv[0] dans un code portable.

Sources

À toi d'écrire le code.