Perché abbiamo bisogno di argc mentre c'è sempre un null alla fine di argv?


117

Sembra che argv[argc]sia sempre NULL, quindi penso che possiamo attraversare l'elenco degli argomenti senza argc. Un singolo whileciclo lo farà.

Se c'è sempre un NULLalla fine di argv, perché ne abbiamo bisogno argc?


17
Probabilmente è una questione di comodità. Offre al programmatore un modo semplice per eseguire il salvataggio anticipato se non ci sono abbastanza argomenti, senza loop. Altrimenti avremmo sicuramente funzioni chiamate che int argc(char *argv[])fanno esattamente questo :-))
cnicutar

5
Giusto per essere chiari, "\0"non è la stessa cosa del puntatore NULL ( 0è equivalente a NULL in C ++)
Mats Petersson

31
Perché abbiamo bisogno che argv [argc] sia NULL se abbiamo argc?
Ambroz Bizjak

7
In quale altro modo determineresti il ​​numero di argomenti in tempo costante?
avakar

4
Non pensare che i tag linux / unix siano appropriati qui, poiché questo comportamento dovrebbe essere vero per tutti i compilatori in tutti i sistemi operativi.
Darrel Hoffman

Risposte:


106

Sì, argv[argc]==NULLè garantito. Vedere C11 5.1.2.2.1 Avvio del programma (enfasi mia)

Se vengono dichiarati, i parametri della funzione principale devono obbedire ai seguenti vincoli:

Il valore di argc non deve essere negativo. argv [argc] deve essere un puntatore nullo.

Fornire argcquindi non è vitale ma è comunque utile. Tra le altre cose, consente di verificare rapidamente che sia stato passato il numero corretto di argomenti.

Modifica: la domanda è stata modificata per includere C ++. n3337 bozza 3.6.1 La funzione principale dice

2 ... argc è il numero di argomenti passati al programma dall'ambiente in cui il programma viene eseguito. .... Il valore di argc non deve essere negativo. Il valore di argv [argc] deve essere 0 .


36
E argcpotrebbe essere molto grande, perché la shell sta facendo l'espansione (in modo in ls *la *si espande dalla shell prima execvedi /bin/lseseguibile). Sul mio sistema, posso avere argcdiverse centinaia di migliaia.
Basile Starynkevitch

È piuttosto interessante, non mi è mai venuto in mente poiché l'ho sempre considerato argcsufficiente, ma posso sicuramente pensare a situazioni in cui questa garanzia sarebbe rilevante e persino richiesta. +1
Thomas

6
@BasileStarynkevitch Il tempo di passare semplicemente attraverso un array di valori di puntatore una volta in più fino a NULL, per ottenere il conteggio, è minuscolo rispetto al tempo già speso per generare l'array di puntatori, e ancora più irrilevante rispetto all'utilizzo effettivo di ciascun valore di argomento nel programma. E se si controlla solo se il conteggio degli argomenti è maggiore di N, non è necessario passare attraverso l'intero array. Tuttavia, sono pienamente d'accordo, questa argcera ed è una buona cosa.
hyde

43

Sì, argv[argc]è garantito che sia un puntatore nullo. argcè usato per comodità.

Citando la spiegazione ufficiale di C99 Rationale, nota le parole controllo ridondante :

Rationale for International Standard - Programming Languages ​​- C §5.1.2.2.1 Avvio del programma

La specificazione di argce argvcome argomenti per mainriconoscere un'ampia pratica precedente. argv[argc]deve essere un puntatore nullo per fornire un controllo ridondante per la fine della lista, anche sulla base della pratica comune.


19

È per motivi storici e compatibilità con il vecchio codice. In origine, non c'era la garanzia che esistesse un puntatore nullo come ultimo elemento dell'array argv. Ma argc è sempre esistito.


... Il che è un peccato, in un certo senso. Se lo avessimo int main(char *argv[], int argc, ...), alcuni programmi potrebbero semplicemente omettere il argcperché non ne hanno bisogno. Opposto (necessario argcma non argv) probabilmente non è mai utile in un programma reale.
hyde

@hyde: vedi commento sopra di Basile Starynkevitch
zentrunix

6

Ne abbiamo "bisogno", perché è richiesto da vari standard.

Siamo liberi di ignorare completamente il valore, ma poiché è il primo parametro di main, dobbiamo averlo nell'elenco dei parametri. In C ++ (e probabilmente dialetti C non standard), puoi semplicemente omettere il nome del parametro, come questo frammento C ++ (facile da convertire in C):

#include <stdio.h> // C-compatible include, guarantees puts in global namespace

// program will print contents of argv, one item per line, starting from argv[0]

int main(int /*argc*/, char *argv[]) { // uncomment argc for C

    //(void)argc; // uncomment statement for C

    for (int i=0; argv[i]; ++i) {
        puts(argv[i]);
    }

    return 0;
}

Nello standard C, con le impostazioni comuni degli avvisi, il parametro inutilizzato genera un avviso, che può essere corretto da un'istruzione come la (void)argc;quale fa sì che il nome venga utilizzato senza generare alcun codice.

argcè bello averlo, perché altrimenti molti programmi avrebbero bisogno di controllare i parametri per ottenere il conteggio. Inoltre, in molti linguaggi di programmazione con array che hanno lunghezza, non c'è alcun argcparametro, c'è solo un array con gli elementi.


La domanda riguarda sia C che C ++. In C, il nome del parametro è obbligatorio.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.