Qual è la dichiarazione corretta di main?


147

Qual è la firma corretta della mainfunzione in C ++? Qual è il tipo di ritorno corretto e cosa significa restituire un valore main? Quali sono i tipi di parametri consentiti e quali sono i loro significati?

Questo è specifico del sistema? Queste regole sono cambiate nel tempo? Cosa succede se li violo?


1
Ciò è strettamente correlato o duplicato di Cosa dovrebbe maintornare in C e C ++ .
Jonathan Leffler,

@JonathanLeffler Non scherzo ... è stato aggiunto all'elenco dei duplicati nella revisione 6 circa 8 mesi fa.
Fredoverflow,

Risposte:


192

La mainfunzione deve essere dichiarata come funzione non membro nello spazio dei nomi globale. Ciò significa che non può essere una funzione membro statica o non statica di una classe, né può essere collocata in uno spazio dei nomi (anche lo spazio dei nomi senza nome).

Il nome mainnon è riservato in C ++ tranne che come funzione nello spazio dei nomi globale. Sei libero di dichiarare altre entità nominate main, tra cui classi, variabili, enumerazioni, funzioni membro e funzioni non membri non presenti nello spazio dei nomi globale.

È possibile dichiarare una funzione denominata maincome funzione membro o in uno spazio dei nomi, ma tale funzione non sarebbe la mainfunzione che designa l'inizio del programma.

La mainfunzione non può essere dichiarata come statico inline. Inoltre non può essere sovraccaricato; può esserci solo una funzione nominata mainnello spazio dei nomi globale.

Il main funzione non può essere utilizzata nel tuo programma: non ti è consentito chiamare la mainfunzione da nessuna parte del tuo codice, né puoi prendere il suo indirizzo.

Il tipo di restituzione di maindeve essereint . Nessun altro tipo restituito è consentito (questa regola è in grassetto perché è molto comune vedere programmi errati che dichiaranomain con un tipo di ritorno void; questa è probabilmente la regola più frequentemente violata relativa alla mainfunzione).

Ci sono due dichiarazioni di main che devono essere consentite:

int main()               // (1)
int main(int, char*[])   // (2)

Nel (1) non ci sono parametri.

In (2) , ci sono due parametri e sono convenzionalmente nominati argce argv, rispettivamente. argvè un puntatore a un array di stringhe C che rappresentano gli argomenti del programma. argcè il numero di argomenti nella argvmatrice.

Generalmente, argv[0] contiene il nome del programma, ma non è sempre così. argv[argc]è garantito per essere un puntatore nullo.

Si noti che poiché un argomento di tipo array (come char*[]) è in realtà solo un argomento di tipo puntatore sotto mentite spoglie, i due seguenti sono entrambi modi validi per scrivere (2) ed entrambi significano esattamente la stessa cosa:

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

Alcune implementazioni possono consentire altri tipi e numeri di parametri; dovresti controllare la documentazione della tua implementazione per vedere cosa supporta.

main()si prevede che restituisca zero per indicare il successo e diverso da zero per indicare il fallimento. Non è necessario scrivere esplicitamente returnun'istruzione in main(): se si lascia main()restituire senza un'istruzione esplicita return, è lo stesso di se si fosse scritto return 0;. I seguenti duemain() funzioni hanno lo stesso comportamento:

int main() { }
int main() { return 0; }

Esistono due macro EXIT_SUCCESSe EXIT_FAILURE, definite in<cstdlib> che possono anche essere restituite main()per indicare rispettivamente successo e fallimento.

Il valore restituito da main() viene passato alla exit()funzione, che termina il programma.

Si noti che tutto ciò si applica solo durante la compilazione per un ambiente ospitato (informalmente, un ambiente in cui si dispone di una libreria standard completa e c'è un sistema operativo che esegue il programma). È anche possibile compilare un programma C ++ per un ambiente indipendente (ad esempio alcuni tipi di sistemi incorporati), nel qual caso l'avvio e la chiusura sono completamente definiti dall'implementazione e main()potrebbe non essere nemmeno necessaria una funzione. Se stai scrivendo C ++ per un moderno sistema operativo desktop, stai compilando per un ambiente ospitato.


1
IIRC gli unici valori restituiti garantiti sono 0, EXIT_SUCCESS (stesso effetto di 0) ed EXIT_FAILURE. EDIT: Ah, OK, possono essere restituiti altri valori di stato diversi da zero, ma con significato definito dall'implementazione. Solo EXIT_FAILURE può essere interpretato in qualche modo come un valore di errore.
Derrick Turk,

4
@Synetech: la domanda nella prima frase si pone: "Qual è la firma corretta della funzione principale in C ++?" e la domanda è taggata sia [c ++] che [c ++ - faq]. Non posso farne a meno se gli utenti Java o C # (o chiunque altro) sono ancora confusi. C # richiede Maindi essere una funzione membro statica perché non ha nemmeno funzioni non membro. Anche C89 richiede maindi tornare int. Non ho abbastanza familiarità con K&R C per conoscere le sue regole esatte, ma immagino che maindebba anche tornare, intpoiché mainnessun tipo di ritorno era abbastanza comune e nessun tipo = implicito intin K&R.
James McNellis,

3
@Suhail: Perché lo standard linguistico dice che deve essere il tipo restituito int.
James McNellis,

1
@Suhail: Sì. Il tuo codice non sarà C ++ corretto e molti compilatori rifiuteranno il tuo codice.
James McNellis,

2
@Suhail: Visual C ++ consente un voidtipo restituito come estensione del linguaggio . I compilatori che non lo consentono includono GCC e Comeau.
James McNellis,

15

Da documenti standard., 3.6.1.2 Funzione principale ,

Deve avere un tipo restituito di tipo int, ma per il resto il suo tipo è definito dall'implementazione. Tutte le implementazioni devono consentire entrambe le seguenti definizioni di main:

int main() { / ... / } e int main(int argc, char* argv[]) { / ... / }

In quest'ultima forma argcdeve essere indicato il numero di argomenti passati al programma dall'ambiente in cui viene eseguito il programma. Se argc è diverso da zero, questi argomenti devono essere forniti in argv [0] tramite argv [argc-1] come puntatori all'iniziale caratteri di stringhe multibyte con terminazione null .....

Spero che aiuti..


2
c'è qualche motivo specifico per cui maindovrebbe essere il tipo di reso int?
Suhail Gupta,

1
@SuhailGupta: in modo che il processo di chiamata sappia se questo processo deve essere considerato corretto o meno. Consentire voidinterruzioni quel modello. Non ha nemmeno senso se tu significassi "ritenere sempre il successo". Perché non hai modo di dire se il processo in realtà è fallito, quindi hai davvero avuto successo? No, ritorna int.
Corse di leggerezza in orbita

4

La formulazione esatta dell'ultimo standard pubblicato (C ++ 14) è:

Un'attuazione deve consentire entrambi

  • una funzione di ()ritorno inte

  • una funzione di (int, puntatore a puntatore al char)ritornoint

come il tipo di main.

Ciò chiarisce che sono consentite ortografie alternative purché il tipo di mainsia il tipo int()o int(int, char**). Quindi sono anche consentiti:

  • int main(void)
  • auto main() -> int
  • int main ( )
  • signed int main()
  • typedef char **a; typedef int b, e; e main(b d, a c)

1
NB. Ho pubblicato questa risposta come nei commenti a un altro thread, qualcuno ha cercato di citare questo thread come prova che int main(void)non era corretta in C ++.
MM

3
@Stargateur auto main() -> intnon ha un tipo di restituzione dedotto. Fai attenzione a {in "(auto main () {... non è consentito)" e per favore impara a sapere quando non conosci ancora abbastanza per aggiungere qualcosa di significativo.

3

Le due reti valide sono int main()e int main(int, char*[]). Qualsiasi altra cosa può essere compilata o meno. Se mainnon restituisce esplicitamente un valore, viene restituito implicitamente 0 .


1
Non ho mai visto il codice non essere compilato quando menziono il tipo restituito di mainessere nullo. C'è qualche motivo specifico per cui il tipo di ritorno di main dovrebbe essere int?
Suhail Gupta,

4
La specifica della lingua dice che main deve avere un tipo restituito di int. Qualsiasi altro tipo di ritorno consentito dal compilatore è un miglioramento specifico del compilatore. Fondamentalmente l'uso di void significa che stai programmando in un linguaggio simile ma non C ++.
stonemetal

2
Il motivo per cui lo standard richiede un inttipo di ritorno mainè che questo valore viene passato alla shell come codice di uscita del programma e si shaspetta un int.
Uckelman,

Forse la ragione è la disciplina? Può esserci più di un percorso. Se il tipo restituito è void, sono tutti silenziosi. Con intdobbiamo definire il valore di uscita specifico per ogni ritorno da main.
Andreas Spindler,

2

Dettagli sui valori di ritorno e il loro significato

Per 3.6.1 ([basic.start.main] ):

Un'istruzione return in mainha l'effetto di lasciare la mainfunzione (distruggere qualsiasi oggetto con durata di memorizzazione automatica) e chiamare std::exitcon il valore restituito come argomento. Se il controllo raggiunge la fine mainsenza incontrare returnun'istruzione, l'effetto è quello dell'esecuzione

return 0;

Il comportamento di std::exit è dettagliato nella sezione 18.5 ( [support.start.term]) e descrive il codice di stato:

Infine, il controllo viene restituito all'ambiente host. Se lo stato è zero o EXIT_SUCCESS, viene restituita una forma definita dall'implementazione della terminazione riuscita dello stato. Se lo stato è EXIT_FAILURE, viene restituita una forma definita dall'implementazione della terminazione non riuscita dello stato. Altrimenti lo stato restituito è definito dall'implementazione.

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.