Cosa significa int argc, char * argv []?


508

In molti IDE e compilatori C ++, quando genera la funzione principale per te, si presenta così:

int main(int argc, char *argv[])

Quando codice C ++ senza un IDE, solo con un compilatore della riga di comando, digito:

int main()

senza parametri. Cosa significa questo ed è vitale per il mio programma?


47
Se il tuo programma ignorerà gli argomenti della riga di comando, allora quello che scrivi va bene. Se il programma deve elaborare gli argomenti della riga di comando, l'IDE sta eseguendo correttamente.
Jonathan Leffler,

30
Un suggerimento per gli hacker: prova a dichiarare int main(int argc, char* argv[], char* envp[])e stampare l'ultimo argomento. ;)
ulidtko,

7
@ulidtko non è bene che stai insegnando ai neofiti a introdurre vulnerabilità nei loro programmi;)
Gab 是 好人

13
@Gab in che modo la semplice stampa delle variabili di ambiente può portare alla vulnerabilità? Basta non trasmettere le stringhe contaminate alla lettera system(), chiamate DB, ecc. Come al solito con l'input dell'utente.
Ulidtko,

2
@ulidtko Interessante .. Puoi spiegare perché non devi passare stringhe contaminate, query db, ecc. mentre usi l' char **envpargomento?
Master James,

Risposte:


651

argve argccome vengono passati gli argomenti della riga di comando main()in C e C ++.

argcsarà il numero di stringhe a cui punta argv. Questo (in pratica) sarà 1 più il numero di argomenti, poiché praticamente tutte le implementazioni anteporranno il nome del programma all'array.

Le variabili sono nominate argc( conteggio degli argomenti ) e argv( vettore degli argomenti ) per convenzione, ma possono avere qualsiasi identificatore valido: int main(int num_args, char** arg_strings)è ugualmente valido.

Possono anche essere omessi del tutto, cedendo int main(), se non si intende elaborare argomenti da riga di comando.

Prova il seguente programma:

#include <iostream>

int main(int argc, char** argv) {
    std::cout << "Have " << argc << " arguments:" << std::endl;
    for (int i = 0; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}

Eseguendolo con ./test a1 b2 c3verrà emesso

Have 4 arguments:
./test
a1
b2
c3

8
argcpuò essere 0, nel qual caso argvpuò essere NULL. È consentito dallo standard AFAIK. Non ho mai sentito parlare di un sistema che lo fa in pratica, ma certamente potrebbe esistere e non violerebbe alcun standard.
Chuck,

77
@Chuck: Poiché "Il valore di argv[argc]deve essere 0" (C ++ 03 §3.6.1 / 2), argvnon può essere nullo.
James McNellis,

20
@Chuck: C (almeno C99) ha lo stesso requisito.
James McNellis,

2
Pensato che dovrei aggiungere, questo è lo stesso nella maggior parte dei sistemi là fuori, sebbene siano astratti alcune volte. Ad esempio, in Pascal / Delphi / Lazarus, ottieni; ParamStr e ParamCount (se la memoria mi serve bene). Il mio punto è che quando (se mai) scrivete applicazioni native in altre lingue / ose, c'è una buona probabilità che quanto sopra sia definito per voi da usare e, funzionano perfettamente allo stesso modo (elenco conteggi / stringhe) in tutti i sistemi che supportano loro.
Christian,

8
@ EmilVikström No, è un errore grave che probabilmente si traduce in un segfault. *NULLnon è assolutamente uguale a NULL.
meagar

52

argcè il numero di argomenti passati nel programma dalla riga di comando ed argvè l'array di argomenti.

Puoi scorrere gli argomenti conoscendone il numero come:

for(int i = 0; i < argc; i++)
{
    // argv[i] is the argument at index i
}

19

Supponiamo che tu esegua il tuo programma così (usando la shsintassi):

myprog arg1 arg2 'arg 3'

Se hai dichiarato il tuo principale come int main(int argc, char *argv[]), quindi (nella maggior parte degli ambienti), il tuo main()sarà chiamato come se fosse:

p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));

Tuttavia, se hai dichiarato il tuo principale come int main(), verrà chiamato qualcosa del genere

exit(main());

e non ottieni gli argomenti passati.

Altre due cose da notare:

  1. Queste sono le uniche due firme obbligatorie standard per main. Se una particolare piattaforma accetta argomenti aggiuntivi o un diverso tipo di ritorno, questa è un'estensione e non dovrebbe essere invocata in un programma portatile.
  2. *argv[]e **argvsono esattamente equivalenti, quindi puoi scrivere int main(int argc, char *argv[])come int main(int argc, char **argv).

2
Se siamo tecnici, basic.start.main/2consentiamo esplicitamente versioni aggiuntive definite dall'implementazione di main(), a condizione che l'implementazione fornisca le due versioni predefinite. Quindi, non sono esattamente non conformi. Il più comune è uno envp, che è così ben noto sia in C e C ++ che è letteralmente la prima voce nella sezione J.5 (estensioni comuni) dello standard C .
Justin Time - Ripristina Monica il

1
Grazie per la bella pedanteria @Justin. Risposta aggiornata per essere più corretta.
Toby Speight,

Nessuna idea - ti suggerisco di creare un esempio riproducibile minimo e chiederlo (supponendo che il processo non sia sufficiente per aiutarti a rispondere da solo).
Toby Speight,

9

I parametri per mainrappresentare i parametri della riga di comando forniti al programma all'avvio. Il argcparametro rappresenta il numero di argomenti della riga di comando ed char *argv[]è un array di stringhe (puntatori di caratteri) che rappresentano i singoli argomenti forniti sulla riga di comando.


2
Argv [] ha sempre argv [arg] come puntatore null. e Argv [0] è sempre il (percorso completo) / nome eseguibile come stringa nul terminata
user3629249

3
@ user3629249: non necessariamente; argv[0]è qualunque cosa il programma che ha lanciato il programma C gli abbia dato argv[0]. Nel caso di Bash, spesso è (forse sempre) il percorso dell'eseguibile, ma Bash non è l'unico programma che esegue altri programmi. E 'permissisble, anche se eccentrico, da utilizzare: char *args[] = { "cat", "/dev/null", "/etc/passwd", 0 }; execv("/bin/ls", args);. Su molti sistemi, il valore visto dal programma argv[0]sarà cat, anche se l'eseguibile è /bin/ls.
Jonathan Leffler,

7

La mainfunzione può avere due parametri argce argv. argcè un intparametro intero ( ) ed è il numero di argomenti passati al programma.

Il nome del programma è sempre il primo argomento, quindi ci sarà almeno un argomento in un programma e il valore minimo di argcsarà uno. Ma se un programma ha due argomenti, il valore di argcsarà tre.

Il parametro argvpunta a una matrice di stringhe e viene chiamato argomento vettoriale . È un array di stringhe monodimensionali di argomenti di funzioni.


5
int main();

Questa è una semplice dichiarazione. Non può accettare argomenti da riga di comando.

int main(int argc, char* argv[]);

Questa dichiarazione viene utilizzata quando il programma deve accettare argomenti della riga di comando. Quando eseguito in questo modo:

myprogram arg1 arg2 arg3

argco Argument Count, verrà impostato su 4 (quattro argomenti) e argv, o Argument Vectors, verrà popolato con puntatori di stringa a "myprogram", "arg1", "arg2" e "arg3". Il programma invocation ( myprogram) è incluso negli argomenti!

In alternativa, è possibile utilizzare:

int main(int argc, char** argv);

Anche questo è valido.

C'è un altro parametro che puoi aggiungere:

int main (int argc, char *argv[], char *envp[])

Il envpparametro contiene anche variabili di ambiente. Ogni voce segue questo formato:

VARIABLENAME=VariableValue

come questo:

SHELL=/bin/bash    

L'elenco delle variabili di ambiente ha una terminazione null.

IMPORTANTE: NON utilizzare alcuno argvo envpvalore direttamente nelle chiamate a system()! Questo è un enorme buco nella sicurezza poiché gli utenti malintenzionati potrebbero impostare variabili di ambiente su comandi da riga di comando e (potenzialmente) causare danni ingenti. In generale, semplicemente non usare system(). C'è quasi sempre una soluzione migliore implementata attraverso le librerie C.


3

Il primo parametro è il numero di argomenti forniti e il secondo parametro è un elenco di stringhe che rappresentano tali argomenti.


7
la prima voce in argv [0] è il nome del programma, non un argomento
user3629249

@ user3629249 Nome del programma con percorso del programma. ;)
Master James,

1

Entrambi

int main(int argc, char *argv[]);
int main();

sono definizioni legali del punto di ingresso per un programma C o C ++. Stroustrup: le domande frequenti su stile e tecnica in C ++ descrivono alcune delle variazioni possibili o legali per la tua funzione principale.


4
Potrebbe voler rendere nullo in ... int main()==> int main(void)... per compatibilità e leggibilità. Non so se tutte le versioni precedenti di C consentano alle funzioni void di avere un elenco di parametri vuoto nella dichiarazione.
dylnmc,

1
@dylnmc questo non fornisce alcun guadagno di leggibilità ed è esattamente equivalente in tutte le versioni di C ++. Solo in C questo ha una differenza, ma solo nelle dichiarazioni, non nella definizione.
Ruslan,

@Ruslan Mi dispiace, l'ho pubblicato quando stavo imparando C, e avrei potuto leggere che nelle primissime versioni di C voidè richiesto. Non citarmi su questo, e ora so che è un commento un po 'sciocco. Non può far male, però.
dylnmc,

cosa succede se argc <3 restituisce un errore? cosa potrebbe andare storto?
AVI
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.