Cosa dovrebbe restituire main () in C e C ++?


695

28
Penso ancora che sia anche abbastanza vago. Definisci "più efficiente" per me. Efficiente in che senso? Nel senso di occupare meno memoria? Nel senso di correre più veloce? Riesco a vedere le risposte utili ma penso ancora che la domanda sia formulata piuttosto male.
Onorio Catenacci,

7
Pish posh, il contesto di efficiente è ovvio qui, specialmente con gli esempi (che sono probabilmente lì per chiarire la definizione di "efficiente"). Si spera che il povero buffer non sia strisciato in un buco e rimpianga completamente la domanda. Si potrebbe dire, indipendentemente da void o int, viene restituito un valore, quindi non ha alcun impatto sulla dimensione del file, sulle operazioni eseguite o sulla memoria allocata. E le persone, nella maggior parte dei sistemi operativi, tendono a restituire 0 in caso di successo e qualcos'altro in caso di successo o fallimento, ma non esiste uno standard. In definitiva, nessuna differenza di efficienza in alcun modo ovvio.
Kit

"corretto (il più efficiente)" non ha senso. Efficiente è una cosa, corretta è un'altra. mainviene chiamato una volta (e in C ++ può essere chiamato solo una volta: nessuna ricorsione). Se non si desidera che l'esecuzione impieghi molto tempo main, non richiamare il programma un gran numero di volte: fare in modo che il programma attui la ripetizione.
Kaz,

2
Trovo interessante che nessuna delle risposte, per quanto posso dire, fornisca un esempio pienamente funzionante, comprese le #includedichiarazioni
puk

3
I valori di ritorno non hanno senso su una piattaforma senza sistema operativo. Non stai tornando a niente. Se si colpisce un returnin main(...)su un dispositivo embedded, il sistema entra in uno stato imprevedibile e la lavatrice diventerà consapevoli di sé e cercare di ucciderti. Quindi, usiamo void main()in quel caso. Questa è una pratica standard del settore nell'incorporazione bare metal.
3Daveva il

Risposte:


570

Il valore restituito per mainindica come è uscito il programma. L'uscita normale è rappresentata da un valore di ritorno 0 da main. L'uscita anomala è segnalata da un ritorno diverso da zero, ma non esiste uno standard per l'interpretazione dei codici diversi da zero. Come notato da altri, void main()è vietato dallo standard C ++ e non deve essere utilizzato. Le mainfirme C ++ valide sono:

int main()

e

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

che equivale a

int main(int argc, char** argv)

Vale anche la pena notare che in C ++, int main()può essere lasciato senza un'istruzione return, a quel punto il valore predefinito è restituire 0. Questo è vero anche con un programma C99. Se return 0;debba essere omesso o meno è aperto al dibattito. La gamma di firme principali del programma C valida è molto maggiore.

L'efficienza non è un problema con la mainfunzione. Può essere inserito e lasciato solo una volta (segnando l'inizio e la fine del programma) secondo lo standard C ++. Per C, il rientro main()è consentito, ma dovrebbe essere evitato.


69
main può essere inserito / lasciato più volte, ma quel programma probabilmente non vincerà alcun premio di design;)
korona,

13
C99 ha anche la caratteristica errata di C ++ che raggiungere la fine della funzione main () equivale a restituire 0 - se main () è definito per restituire un tipo compatibile con int (sezione 5.1.2.2.3).
Jonathan Leffler,

62
il rientro principale non è C ++ valido. Esplicitamente nello standard, 3.6.1.3 afferma che "main non deve essere utilizzato all'interno di un programma"
workmad3,

117
stdlib.h fornisce EXIT_SUCCESS e EXIT_FAILURE per questo scopo
Clay

20
0 e non zero sono corretti ma del tutto privi di significato per qualcuno che legge il tuo codice. Questa domanda è la prova che le persone non sanno quali siano i codici validi / non validi. EXIT_SUCCESS / EXIT_FAILURE sono molto più chiari.
JaredPar,

169

La risposta accettata sembra essere indirizzata al C ++, quindi ho pensato di aggiungere una risposta che riguardi il C, e questo differisce in alcuni modi.

ISO / IEC 9899: 1989 (C90):

main() dovrebbe essere dichiarato come:

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

O equivalente. Ad esempio, int main(int argc, char *argv[])equivale al secondo. Inoltre, il inttipo restituito può essere omesso in quanto predefinito.

Se un'implementazione lo consente, main()può essere dichiarata in altri modi, ma ciò rende l'implementazione del programma definita e non più strettamente conforme.

Lo standard definisce 3 valori per la restituzione che sono rigorosamente conformi (vale a dire, non si basa sul comportamento definito dall'implementazione): 0e EXIT_SUCCESSper una terminazione corretta e EXIT_FAILUREper una terminazione non riuscita. Tutti gli altri valori sono non standard e l'implementazione definita. main()deve avere una returndichiarazione esplicita alla fine per evitare comportamenti indefiniti.

Infine, non c'è nulla di sbagliato dal punto di vista standard nella chiamata main()da un programma.

ISO / IEC 9899: 1999 (C99):

Per C99, tutto è uguale a sopra tranne:

  • Il inttipo restituito non può essere omesso.
  • È possibile omettere la dichiarazione di reso da main(). Se lo fai e hai main()finito, c'è un implicito return 0.

1
@Lundin Non penso che tu abbia bisogno di un preventivo per dire che a qualcuno è permesso fare un compilatore che accetta programmi non conformi allo standard, o avere un compilatore non conforme allo standard. Questa è conoscenza comune e buon senso
KABoissonneault

4
@KABoissonneault Il comportamento definito dall'implementazione è un termine dallo standard, al contrario di un comportamento completamente non documentato. Se si implementa qualcosa elencato come comportamento definito dall'implementazione, si segue comunque lo standard. In questo caso C89, che è stato citato, non elenca tale comportamento definito dall'implementazione, quindi la necessità di un preventivo, per dimostrare che non sta solo inventando le cose di punto in bianco.
Lundin,

1
@Lundin Lo stai vedendo nel modo sbagliato. Ciò di cui stiamo parlando non è un comportamento definito dall'implementazione, stiamo parlando di un'implementazione che si discosta dallo standard se lo scelgono. È più come un bambino che disobbedisce ai loro genitori: non hai bisogno di una citazione dei genitori per dirti in che modo un bambino può andare contro ciò che i genitori hanno detto. Sai solo che nel momento in cui il bambino sceglie di farlo, non sono più conformi alle corporazioni dei genitori
KABoissonneault

2
@KABoissonneault La parte che ho citato nel mio commento riguarda sicuramente il comportamento definito dall'implementazione (al contrario delle estensioni del compilatore non standard ). Quindi sto parlando del comportamento definito dall'implementazione. Se stai avendo un monologo su qualcos'altro, buona fortuna con quello.
Lundin,

1
@Lundin Immagino che la formulazione nella citazione sia confusa (la parte in cui dicono "ma questo definisce l'implementazione del programma") ma sono abbastanza sicuro che la persona stesse parlando di comportamenti non standard (come detto in "Se un'implementazione lo consente "e" e non è più strettamente conforme [allo standard] ") rispetto al comportamento definito dall'attuazione effettiva. La persona dovrebbe sicuramente riformulare la sua risposta, ma non credo ancora che sia necessaria una citazione dallo standard su questo
KABoissonneault

117

Standard C - Ambiente ospitato

Per un ambiente ospitato (quello normale), lo standard C11 (ISO / IEC 9899: 2011) dice:

5.1.2.2.1 Avvio del programma

La funzione chiamata all'avvio del programma è denominata main. L'implementazione non dichiara alcun prototipo per questa funzione. Deve essere definito con un tipo di ritorno inte senza parametri:

int main(void) { /* ... */ }

o con due parametri (indicati qui come argce argv, sebbene sia possibile utilizzare qualsiasi nome, poiché sono locali alla funzione in cui sono dichiarati):

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

o equivalente; 10) o in qualche altro modo definito dall'implementazione.

Se sono dichiarati, i parametri della funzione principale devono rispettare i seguenti vincoli:

  • Il valore di argcnon è negativo.
  • argv[argc] deve essere un puntatore nullo.
  • Se il valore di argcè maggiore di zero, i membri dell'array argv[0]tramite argv[argc-1]inclusivo devono contenere puntatori alle stringhe, che ricevono valori definiti dall'implementazione dall'ambiente host prima dell'avvio del programma. L'intento è fornire al programma le informazioni determinate prima dell'avvio del programma altrove nell'ambiente ospitato. Se l'ambiente host non è in grado di fornire stringhe con lettere sia maiuscole che minuscole, l'implementazione deve garantire che le stringhe siano ricevute in minuscolo.
  • Se il valore di argcè maggiore di zero, la stringa indicata da argv[0] rappresenta il nome del programma; argv[0][0]deve essere il carattere null se il nome del programma non è disponibile dall'ambiente host. Se il valore di argcè maggiore di uno, le stringhe indicate da argv[1]attraverso argv[argc-1] rappresentano i parametri del programma.
  • I parametri argce argvle stringhe a cui punta l' argvarray devono essere modificabili dal programma e conservare i loro ultimi valori memorizzati tra l'avvio e la fine del programma.

10) Pertanto, intpuò essere sostituito da un nome typedef definito come int, oppure il tipo di argvpuò essere scritto come char **argve così via.

Terminazione del programma in C99 o C11

Il valore restituito da main()viene trasmesso all '"ambiente" in modo definito dall'implementazione.

5.1.2.2.3 Terminazione del programma

1 Se il tipo restituito della mainfunzione è compatibile con un tipo int, un ritorno dalla chiamata iniziale alla mainfunzione equivale a chiamare la exitfunzione con il valore restituito dalla mainfunzione come argomento; 11) il raggiungimento di quello }che termina la mainfunzione restituisce un valore di 0. Se il tipo restituito non è compatibile int, lo stato di terminazione restituito all'ambiente host non è specificato.

11) In conformità al punto 6.2.4, la durata di vita degli oggetti con durata di conservazione automatica dichiarata main sarà terminata nel primo caso, anche se non nel secondo.

Si noti che 0è obbligatorio come "successo". Puoi usare EXIT_FAILUREe EXIT_SUCCESSda <stdlib.h>se preferisci, ma 0 è ben definito, e lo è anche 1. Vedi anche Codici di uscita superiori a 255 - possibili? .

In C89 (e quindi in Microsoft C), non ci sono istruzioni su cosa succede se la main()funzione ritorna ma non specifica un valore di ritorno; porta quindi a comportamenti indefiniti.

7.22.4.4 La exitfunzione

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

Standard C ++ - Ambiente ospitato

Lo standard C ++ 11 (ISO / IEC 14882: 2011) afferma:

3.6.1 Funzione principale [basic.start.main]

¶1 Un programma deve contenere una funzione globale chiamata main, che è l'inizio designato del programma. [...]

¶2 Un'attuazione non deve predefinire la funzione principale. Questa funzione non deve essere sovraccaricata. 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 vengono forniti in argv[0] attraverso argv[argc-1]come puntatori ai caratteri iniziali di stringhe multibyte null-terminate (NTMBSs) (17.5.2.1.4.2) e argv[0]sono il puntatore al carattere iniziale di un NTMBS che rappresenta il nome utilizzato per invocare il programma o "". Il valore di argcdeve essere non negativo. Il valore di argv[argc] deve essere 0. [Nota: si consiglia di aggiungere ulteriori parametri (facoltativi) dopo argv. —Endola nota]

¶3 La funzione mainnon deve essere utilizzata all'interno di un programma. Il collegamento (3.5) di mainè definito dall'implementazione. [...]

¶5 Un'istruzione return in main ha l'effetto di lasciare la funzione principale (distruggere qualsiasi oggetto con durata di memorizzazione automatica) e chiamare std::exitcon l'argomento il valore restituito. Se il controllo raggiunge la fine di main senza incontrare un'istruzione return, l'effetto è quello dell'esecuzione

return 0;

Lo standard C ++ dice esplicitamente "Essa [la funzione principale] deve avere un tipo restituito di tipo int, ma altrimenti il ​​suo tipo è definito dall'implementazione" e richiede che le stesse due firme dello standard C siano supportate come opzioni. Quindi un 'void main ()' non è direttamente consentito dallo standard C ++, anche se non c'è nulla che possa fare per fermare un'implementazione non standard che consente alternative. Si noti che C ++ proibisce all'utente di chiamare main(ma lo standard C no).

C'è un paragrafo di §18.5 Inizio e fine nello standard C ++ 11 che è identico al paragrafo di §7.22.4.4 La exitfunzione nello standard C11 (citato sopra), a parte una nota a piè di pagina (che documenta semplicemente EXIT_SUCCESSe che EXIT_FAILUREsono definiti in <cstdlib>).

Standard C - Estensione comune

Classicamente, i sistemi Unix supportano una terza variante:

int main(int argc, char **argv, char **envp) { ... }

Il terzo argomento è un elenco di puntatori alle stringhe con terminazione null, ognuno dei quali è una variabile di ambiente che ha un nome, un segno di uguale e un valore (possibilmente vuoto). Se non lo usi, puoi comunque accedere all'ambiente tramite ' extern char **environ;'. Questa variabile globale è unica tra quelle in POSIX in quanto non ha un'intestazione che la dichiara.

Ciò è riconosciuto dalla norma C come estensione comune, documentata nell'allegato J:

J.5.1 Argomenti ambientali

¶1 In un ambiente ospitato, la funzione principale riceve un terzo argomento, char *envp[]che punta a una matrice di puntatori con terminazione nulla char, ciascuno dei quali punta a una stringa che fornisce informazioni sull'ambiente per questa esecuzione del programma (5.1. 2.2.1).

Microsoft C

Il compilatore Microsoft VS 2010 è interessante. Il sito web dice:

La sintassi della dichiarazione per main è

 int main();

o, facoltativamente,

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

In alternativa, le funzioni maine wmainpossono essere dichiarate come voidreturn (nessun valore di ritorno). Se si dichiara maino si wmainannulla la restituzione, non è possibile restituire un codice di uscita al processo padre o al sistema operativo utilizzando un'istruzione return. Per restituire un codice di uscita quando maino wmainviene dichiarato come void, è necessario utilizzare la exitfunzione.

Non mi è chiaro cosa succede (quale codice di uscita viene restituito al genitore o al sistema operativo) quando un programma con void main()esce, e anche il sito Web MS è silenzioso.

È interessante notare che MS non prescrive la versione a due argomenti main()richiesta dagli standard C e C ++. Prescrive solo una forma a tre argomenti in cui si trova il terzo argomento char **envp, un puntatore a un elenco di variabili di ambiente.

La pagina Microsoft elenca anche alcune altre alternative, wmain()che richiedono ampie stringhe di caratteri e altre ancora.

La versione di Microsoft Visual Studio 2005 di questa pagina non è elencata void main()come alternativa. Le versioni da Microsoft Visual Studio 2008 in poi lo fanno.

Standard C - Ambiente indipendente

Come notato in precedenza, i requisiti di cui sopra si applicano agli ambienti ospitati. Se lavori con un ambiente indipendente (che è l'alternativa a un ambiente ospitato), lo standard ha molto meno da dire. Per un ambiente indipendente, non è necessario chiamare la funzione chiamata all'avvio del programma maine non vi sono vincoli sul tipo di ritorno. Lo standard dice:

5.1.2 Ambienti di esecuzione

Sono definiti due ambienti di esecuzione: indipendenti e ospitati. In entrambi i casi, l'avvio del programma si verifica quando una funzione C designata viene chiamata dall'ambiente di esecuzione. Tutti gli oggetti con durata di memorizzazione statica devono essere inizializzati (impostati sui valori iniziali) prima dell'avvio del programma. Le modalità e i tempi di tale inizializzazione sono altrimenti non specificati. La terminazione del programma restituisce il controllo all'ambiente di esecuzione.

5.1.2.1 Ambiente indipendente

In un ambiente indipendente (in cui l'esecuzione del programma C può avvenire senza alcun vantaggio di un sistema operativo), il nome e il tipo della funzione chiamata all'avvio del programma sono definiti dall'implementazione. Qualsiasi struttura di libreria disponibile per un programma indipendente, ad eccezione dell'insieme minimo richiesto dalla clausola 4, è definita dall'implementazione.

L'effetto della conclusione del programma in un ambiente indipendente è definito dall'implementazione.

Il riferimento incrociato alla clausola 4 Conformità si riferisce a questo:

¶5 Un programma strettamente conforme deve utilizzare solo le caratteristiche della lingua e della biblioteca specificate nella presente norma internazionale. 3) Non deve produrre output dipendenti da comportamenti non specificati, non definiti o definiti dall'implementazione e non deve superare alcun limite minimo di implementazione.

¶6 Le due forme di implementazione conforme sono ospitate e indipendenti . Un conforme implementazione ospitata accetta qualsiasi programma rigorosamente conforme. Un conforme implementazione indipendente accetta qualsiasi programma rigorosamente conforme in cui l'uso delle caratteristiche specificate nella clausola libreria (clausola 7) si limita al contenuto delle intestazioni standard <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, e <stdnoreturn.h>. Un'implementazione conforme può avere estensioni (incluse funzioni di libreria aggiuntive), a condizione che non alterino il comportamento di alcun programma strettamente conforme. 4)

¶7 Un programma conforme è accettabile per un'implementazione conforme. 5)

3) Un programma rigorosamente conforme può utilizzare le funzioni condizionali (vedere 6.10.8.3) a condizione che l'uso sia tutelato da un'adeguata direttiva di preelaborazione dell'inclusione condizionale utilizzando la relativa macro. Per esempio:

#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
    /* ... */
    fesetround(FE_UPWARD);
    /* ... */
#endif

4) Ciò implica che un'implementazione conforme non riserva identificatori diversi da quelli esplicitamente riservati nella presente norma internazionale.

5) I programmi rigorosamente conformi devono essere massimamente trasportabili tra le implementazioni conformi. I programmi conformi possono dipendere da funzionalità non portatili di un'implementazione conforme.

È evidente che l'unica intestazione richiesta per un ambiente indipendente che definisce effettivamente qualsiasi funzione è <stdarg.h>(e anche quelle possono essere - e spesso lo sono - solo macro).

Standard C ++ - Ambiente indipendente

Proprio come lo standard C riconosce sia l'ambiente ospitato che quello indipendente, così anche lo standard C ++. (Citazioni da ISO / IEC 14882: 2011.)

1.4 Conformità all'implementazione [intro.compliance]

¶7 Sono definiti due tipi di implementazioni: un'implementazione ospitata e un'implementazione indipendente . Per un'implementazione ospitata, questo standard internazionale definisce l'insieme delle librerie disponibili. Un'implementazione indipendente è quella in cui l'esecuzione può avvenire senza il beneficio di un sistema operativo e ha un set di librerie definito dall'implementazione che include determinate librerie di supporto linguistico (17.6.1.3).

¶8 Un'implementazione conforme può avere estensioni (incluse funzioni di libreria aggiuntive), a condizione che non alterino il comportamento di alcun programma ben formato. Le implementazioni sono necessarie per diagnosticare i programmi che utilizzano tali estensioni mal formate secondo questo standard internazionale. Fatto ciò, tuttavia, possono compilare ed eseguire tali programmi.

¶9 Ciascuna implementazione deve includere la documentazione che identifica tutti i costrutti supportati condizionalmente che non supporta e definisce tutte le caratteristiche specifiche della locale. 3

3) Questa documentazione definisce anche il comportamento definito dall'implementazione; vedi 1.9.

17.6.1.3 Implementazioni indipendenti [conformità]

Sono definiti due tipi di implementazioni: ospitato e indipendente (1.4). Per un'implementazione ospitata, questo standard internazionale descrive l'insieme di intestazioni disponibili.

Un'implementazione indipendente ha un set di intestazioni definito dall'implementazione. Questo set comprende almeno le intestazioni indicate nella tabella 16.

La versione fornita dell'intestazione <cstdlib>dichiara almeno le funzioni abort, atexit, at_quick_exit, exit, e quick_exit(18.5). Le altre intestazioni elencate in questa tabella devono soddisfare gli stessi requisiti previsti per un'implementazione ospitata.

Tabella 16 - Intestazioni C ++ per implementazioni indipendenti

Subclause                           Header(s)
                                    <ciso646>
18.2  Types                         <cstddef>
18.3  Implementation properties     <cfloat> <limits> <climits>
18.4  Integer types                 <cstdint>
18.5  Start and termination         <cstdlib>
18.6  Dynamic memory management     <new>
18.7  Type identification           <typeinfo>
18.8  Exception handling            <exception>
18.9  Initializer lists             <initializer_list>
18.10 Other runtime support         <cstdalign> <cstdarg> <cstdbool>
20.9  Type traits                   <type_traits>
29    Atomics                       <atomic>

Che ne dici di usare int main()in C?

Lo standard §5.1.2.2.1 dello standard C11 mostra la notazione preferita -  int main(void)- ma ci sono anche due esempi nello standard che mostrano int main(): §6.5.3.4 ¶8 e §6.7.6.3 ¶20 . Ora, è importante notare che gli esempi non sono "normativi"; sono solo illustrativi. Se negli esempi ci sono dei bug, questi non influenzano direttamente il testo principale dello standard. Detto questo, sono fortemente indicativi del comportamento previsto, quindi se la norma include int main()in un esempio, suggerisce che int main()non è vietato, anche se non è la notazione preferita.

6.5.3.4 Operatori sizeofe_Alignof

...

¶8 ESEMPIO 3 In questo esempio, la dimensione di un array di lunghezza variabile viene calcolata e restituita da una funzione:

#include <stddef.h>

size_t fsize3(int n)
{
    char b[n+3]; // variable length array
    return sizeof b; // execution time sizeof
}
int main()
{
    size_t size;
    size = fsize3(10); // fsize3 returns 13
    return 0;
}

@DavidBowling: una definizione di funzione come int main(){ … }specifica che la funzione non accetta argomenti, ma non fornisce un prototipo di funzione, AFAICT. Per main()che è raramente un problema; significa che se si hanno chiamate ricorsive a main(), gli argomenti non verranno controllati. Per altre funzioni, è più un problema: quando si chiama la funzione è davvero necessario un prototipo nell'ambito per assicurarsi che gli argomenti siano corretti.
Jonathan Leffler,

1
@DavidBowling: normalmente non si chiama main()ricorsivamente, al di fuori di luoghi come IOCCC. Ho un programma di test che lo fa - principalmente per le novità. Se si dispone int i = 0; int main() { if (i++ < 10) main(i, i * i); return 0; }e si compila con GCC e non si include -Wstrict-prototypes, si compila in modo pulito sotto stringenti avvisi. Se lo è main(void), non riesce a compilare.
Jonathan Leffler,

61

Credo che main()dovrebbe tornare EXIT_SUCCESSo EXIT_FAILURE. Sono definiti instdlib.h


20
0 è anche standard.
Chris Young,

2
@ChrisYoung C'è EXIT_SUCCESSe EXIT_FAILUREperché alcuni sistemi operativi storici (VMS?) Hanno usato un numero diverso da 0 per indicare il successo. Sono 0 ovunque al giorno d'oggi.
fuz,

5
@FUZxxl hai ragione, ma non è in conflitto con il mio commento. EXIT_SUCCESS può effettivamente essere diverso da zero, ma gli standard (C89, C99, C11) definiscono tutti 0 (così come EXIT_SUCCESS) per essere anche una forma definita dall'implementazione della risoluzione con esito positivo dello stato.
Chris Young,

2
@FUZxxl: è vero che il VMS ha usato valori dispari (come 1) per indicare successo e valori pari (come 0) per indicare fallimento. Sfortunatamente, lo standard ANSI C originale è stato interpretato nel senso che EXIT_SUCCESS doveva essere 0, quindi la restituzione di EXIT_SUCCESS dal main ha esattamente il comportamento sbagliato su VMS. La cosa portatile da fare per VMS era usare exit(EXIT_SUCCESS), che faceva sempre la cosa giusta.
Adrian McCarthy,

1
5.1.2.2.3 "Se il tipo restituito della funzione principale è un tipo compatibile con int, un ritorno dalla chiamata iniziale alla funzione principale equivale a chiamare la funzione di uscita con il valore restituito dalla funzione principale come argomento; 11) il raggiungimento di} che termina la funzione principale restituisce un valore di 0. "
Lundin,

38

Si noti che gli standard C e C ++ definiscono due tipi di implementazioni: indipendente e ospitato.

  • Ambiente ospitato C90

    Moduli consentiti 1 :

    int main (void)
    int main (int argc, char *argv[])
    
    main (void)
    main (int argc, char *argv[])
    /*... etc, similar forms with implicit int */

    Commenti:

    I primi due sono esplicitamente indicati come i moduli consentiti, gli altri sono implicitamente consentiti perché C90 ha consentito "int implicito" per i parametri di tipo e funzione di ritorno. Nessun altro modulo è consentito.

  • Ambiente indipendente C90

    È consentita qualsiasi forma o nome di principale 2 .

  • Ambiente ospitato C99

    Moduli consentiti 3 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */

    Commenti:

    C99 ha rimosso "int implicito", quindi main()non è più valido.

    È stata introdotta una frase strana e ambigua "o in qualche modo definito dall'implementazione". Questo può essere interpretato come "i parametri int main()possono variare" o come "main può avere qualsiasi forma definita dall'implementazione".

    Alcuni compilatori hanno scelto di interpretare lo standard in quest'ultimo modo. Probabilmente, non si può facilmente affermare che non sono strettamente conformi citando lo standard in sé, poiché è ambiguo.

    Tuttavia, consentire forme completamente selvagge main()probabilmente non era (?) L'intenzione di questa nuova frase. La logica C99 (non normativa) implica che la frase si riferisce a parametri aggiuntivi a int main 4 .

    Tuttavia, la sezione relativa alla conclusione del programma di ambiente ospitato continua a discutere sul caso in cui main non ritorna int 5 . Sebbene questa sezione non sia normativa per come deve essere dichiarato main, implica sicuramente che main potrebbe essere dichiarata in un modo completamente definito dall'implementazione anche sui sistemi ospitati.

  • Ambiente indipendente C99

    È consentita qualsiasi forma o nome di principale 6 .

  • Ambiente ospitato C11

    Moduli consentiti 7 :

    int main (void)
    int main (int argc, char *argv[])
    /* or in some other implementation-defined manner. */
  • Ambiente indipendente C11

    È consentita qualsiasi forma o nome di principale 8 .


Si noti che int main()non è mai stato elencato come un modulo valido per qualsiasi implementazione ospitata di C in una delle versioni precedenti. In C, a differenza di C ++, ()e (void)hanno significati diversi. La prima è una funzionalità obsoleta che può essere rimossa dalla lingua. Vedi le direzioni linguistiche future per C11:

6.11.6 Dichiaratori di funzioni

L'uso di dichiaratori di funzioni con parentesi vuote (non dichiaratori di tipi di parametri in formato prototipo) è una caratteristica obsoleta.


  • Ambiente ospitato C ++ 03

    Moduli consentiti 9 :

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

    Commenti:

    Nota la parentesi vuota nella prima forma. C ++ e C sono diversi in questo caso, perché in C ++ ciò significa che la funzione non accetta parametri. Ma in C significa che può prendere qualsiasi parametro.

  • Ambiente indipendente C ++ 03

    Il nome della funzione chiamata all'avvio è definito dall'implementazione. Se è nominato main()deve seguire i moduli indicati 10 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])
  • Ambiente ospitato C ++ 11

    Moduli consentiti 11 :

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

    Commenti:

    Il testo dello standard è stato modificato ma ha lo stesso significato.

  • Ambiente indipendente C ++ 11

    Il nome della funzione chiamata all'avvio è definito dall'implementazione. Se è nominato main()deve seguire i moduli indicati 12 :

    // implementation-defined name, or 
    int main ()
    int main (int argc, char *argv[])

Riferimenti

  1. ANSI X3.159-1989 2.1.2.2 Ambiente ospitato. "Avvio del programma"

    La funzione chiamata all'avvio del programma è denominata main. L'implementazione non dichiara alcun prototipo per questa funzione. Deve essere definito con un tipo di ritorno di int e senza parametri:

    int main(void) { /* ... */ } 

    o con due parametri (qui indicati come argc e argv, anche se è possibile utilizzare qualsiasi nome, poiché sono locali alla funzione in cui sono dichiarati):

    int main(int argc, char *argv[]) { /* ... */ }
  2. ANSI X3.159-1989 2.1.2.1 Ambiente indipendente:

    In un ambiente indipendente (in cui l'esecuzione del programma C può avvenire senza alcun vantaggio di un sistema operativo), il nome e il tipo della funzione chiamata all'avvio del programma sono definiti dall'implementazione.

  3. ISO 9899: 1999 5.1.2.2 Ambiente ospitato -> 5.1.2.2.1 Avvio del programma

    La funzione chiamata all'avvio del programma è denominata main. L'implementazione non dichiara alcun prototipo per questa funzione. Deve essere definito con un tipo di ritorno di int e senza parametri:

    int main(void) { /* ... */ } 

    o con due parametri (qui indicati come argc e argv, anche se è possibile utilizzare qualsiasi nome, poiché sono locali alla funzione in cui sono dichiarati):

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

    o equivalente; 9) o in qualche altro modo definito dall'implementazione.

  4. Razionale per lo standard internazionale - Linguaggi di programmazione - C, Revisione 5.10. 5.1.2.2 Ambiente ospitato -> 5.1.2.2.1 Avvio del programma

    Il comportamento degli argomenti a main e dell'interazione di exit, main e atexit (vedi §7.20.4.2) è stato codificato per contenere alcune varietà indesiderate nella rappresentazione delle stringhe di argv e nel significato dei valori restituiti da main.

    La specifica di argc e argv come argomenti per main riconosce un'ampia pratica precedente. argv [argc] deve essere un puntatore nullo per fornire un controllo ridondante per la fine dell'elenco, anche sulla base di una pratica comune.

    main è l'unica funzione che può essere dichiarata in modo portabile con zero o due argomenti. (Il numero di argomenti di altre funzioni deve corrispondere esattamente tra invocazione e definizione.) Questo caso speciale riconosce semplicemente la pratica diffusa di lasciare gli argomenti a main quando il programma non accede alle stringhe di argomenti del programma. Mentre molte implementazioni supportano più di due argomenti per main, tale pratica non è né benedetta né proibita dallo Standard; un programma che definisce main con tre argomenti non è strettamente conforme (vedere §J.5.1.).

  5. ISO 9899: 1999 5.1.2.2 Ambiente ospitato -> 5.1.2.2.3 Terminazione del programma

    Se il tipo restituito della funzione principale è un tipo compatibile con int, un ritorno dalla chiamata iniziale alla funzione principale equivale a chiamare la funzione di uscita con il valore restituito dalla funzione principale come argomento; 11) raggiungendo quello }che termina la funzione principale restituisce un valore pari a 0. Se il tipo restituito non è compatibile con int, lo stato di terminazione restituito all'ambiente host non è specificato.

  6. ISO 9899: 1999 5.1.2.1 Ambiente indipendente

    In un ambiente indipendente (in cui l'esecuzione del programma C può avvenire senza alcun vantaggio di un sistema operativo), il nome e il tipo della funzione chiamata all'avvio del programma sono definiti dall'implementazione.

  7. ISO 9899: 2011 5.1.2.2 Ambiente ospitato -> 5.1.2.2.1 Avvio del programma

    Questa sezione è identica a quella C99 sopra citata.

  8. ISO 9899: 1999 5.1.2.1 Ambiente indipendente

    Questa sezione è identica a quella C99 sopra citata.

  9. ISO 14882: 2003 3.6.1 Funzione principale

    Un'implementazione non deve predefinire la funzione principale. Questa funzione non deve essere sovraccaricata. 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[]) { /* ... */ }
  10. ISO 14882: 2003 3.6.1 Funzione principale

    È definito dall'implementazione se è necessario un programma in un ambiente indipendente per definire una funzione principale.

  11. ISO 14882: 2011 3.6.1 Funzione principale

    Un'implementazione non deve predefinire la funzione principale. Questa funzione non deve essere sovraccaricata. Deve avere un tipo restituito di tipo int, ma per il resto il suo tipo è definito dall'implementazione. Tutte le implementazioni devono consentire entrambe

    - una funzione di () restituendo int e

    - una funzione di (int, puntatore a puntatore a carattere) che restituisce int

    come tipo di main (8.3.5).

  12. ISO 14882: 2011 3.6.1 Funzione principale

    Questa sezione è identica a quella di C ++ 03 citata sopra.


Una domanda: gli standard C ++ significano che anche la firma della funzione di avvio in ambienti indipendenti è definita dall'implementazione? Ad esempio, un'implementazione avrebbe potuto definire la funzione di avvio come: int my_startup_function ()o int my_startup_function (int argc, char *argv[])ma potrebbe avere, ad esempio: anche char my_startup_function (long argc, int *argv[])come funzione di avvio? Immagino di no, vero? Inoltre, non è altrettanto ambiguo?
Utku,

@Utku Può avere qualsiasi firma, purché non abbia un nome, main()perché deve usare una delle firme elencate. Immagino che il più schiacciante sarebbe quello comune void my_startup_function (), dal momento che non ha senso tornare dal programma su sistemi indipendenti.
Lundin,

1
Vedo. Ma se è consentito utilizzare qualsiasi nome e firma per la funzione di avvio, perché non consentire di utilizzare anche una firma diversa main? Scusate se non è una domanda intelligente ma non riesco a capire il ragionamento alla base.
Utku,

@Utku C e C ++ sono diversi lì. Per quanto riguarda il motivo per cui il C ++ lo impone, non ne ho idea, non esiste una logica. Ho il sospetto che il colpevole principale (gioco di parole intenzionale) sia Stroustrup che presto dichiarò che il principale doveva tornare nel periodo. Perché quando ha realizzato la prima versione C ++, è stato utilizzato solo per i sistemi ospitati. Nel post collegato, Stroustrup sembra ancora ignaro dell'esistenza di implementazioni indipendenti: ad esempio, si riferisce in modo ignorante al sottocapitolo di implementazione ospitata dello standard C, ignorando l'esistenza del capitolo 5.1.2.1.
Lundin,

1
La cosa notevole della bozza standard C11 è che sebbene func()sia considerata obsoleta, la bozza stessa utilizza int main()nei suoi stessi esempi.
Antti Haapala,

29

Restituisce 0 in caso di successo e diverso da zero per errore. Questo è lo standard utilizzato dagli script UNIX e DOS per scoprire cosa è successo con il tuo programma.


8

main() in C89 e K&R C i tipi di ritorno non specificati sono impostati su "int".

return 1? return 0?
  1. Se non si scrive un'istruzione return in int main(), la chiusura {restituirà 0 per impostazione predefinita.

  2. return 0o return 1sarà ricevuto dal processo principale. In una shell si inserisce in una variabile di shell e se si esegue il programma da una shell e non si utilizza quella variabile, non è necessario preoccuparsi del valore di ritorno di main().

Vedi Come posso ottenere ciò che ha restituito la mia funzione principale? .

$ ./a.out
$ echo $?

In questo modo puoi vedere che è la variabile $?che riceve il byte meno significativo del valore di ritorno di main().

Negli script Unix e DOS, return 0in genere vengono restituiti in caso di esito positivo e diversi da zero per errore. Questo è lo standard utilizzato dagli script Unix e DOS per scoprire cosa è successo con il tuo programma e controllare l'intero flusso.


4
A rigor di termini, $?non è una variabile d'ambiente; è una variabile predefinita (o integrata) della shell. La differenza è difficile da individuare, ma se si esegue env(senza argomenti), stampa l'ambiente e $?non verrà mostrato nell'ambiente.
Jonathan Leffler,

1
Restituisce 0 automaticamente quando le principali "cadute della fine" sono solo in C ++ e C99 in poi, non in C90.
Kaz,

Errore di battitura: "chiusura {" dovrebbe essere }. SO non mi permetterà di fare una modifica così piccola.
Spencer,

7

Tieni presente che, anche se stai restituendo un int, alcuni sistemi operativi (Windows) troncano il valore restituito a un singolo byte (0-255).


4
Unix fa lo stesso, come probabilmente la maggior parte degli altri sistemi operativi. So che VMS fa cose così incredibili e strane che restituire qualcosa di diverso da EXIT_SUCCESS o EXIT_FAILURE richiede problemi.
Leon Timmermans,

2
MSDN chiede differenze: quando segnalato tramite mscorlib, un codice di uscita è un numero intero a 32 bit con segno . Ciò sembra implicare che le librerie di runtime C che troncano i codici di uscita sono difettose.

Sì, questo non è corretto. Su Windows viene restituito un numero intero a 32 bit (e convertito in unsigned). Questo è lo stesso sui sistemi UNIX con numeri interi a 32 bit. Ma le shell in stile UNIX su entrambi i sistemi manterranno in genere solo un numero intero a 8 bit senza segno.
John McFarlane,

4

Il valore restituito può essere utilizzato dal sistema operativo per verificare come il programma è stato chiuso.

Il valore di ritorno 0 di solito significa OK nella maggior parte dei sistemi operativi (quelli a cui riesco a pensare comunque).

Può anche essere verificato quando si chiama un processo e vedere se il programma è stato chiuso e terminato correttamente.

E ' NON solo una convenzione di programmazione.


Non c'è nulla nella domanda che indichi la presenza di un sistema operativo. Restituire un valore non ha alcun senso in un sistema indipendente.
Lundin,

3

Il valore restituito di main()mostra come è uscito il programma. Se il valore restituito è zerosignifica che l'esecuzione ha avuto esito positivo mentre qualsiasi valore diverso da zero indicherà che qualcosa è andato male nell'esecuzione.


1
Questo è un commento, non una risposta alla domanda.
Lundin,

2

Avevo l'impressione che lo standard specifica che main non ha bisogno di un valore di ritorno poiché un ritorno di successo era basato sul sistema operativo (zero in uno poteva essere un successo o un fallimento in un altro), quindi l'assenza di ritorno era un segnale per compilatore per inserire il ritorno riuscito stesso.

Tuttavia di solito restituisco 0.


C99 (e C ++ 98) consentono di omettere l'istruzione return da main; C89 non consente di omettere la dichiarazione di reso.
Jonathan Leffler,

Questo è un commento, non una risposta.
Lundin,

Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post.
Steve Lillis,

6
@SteveLillis: Nel 2008 SO non aveva una sezione commenti.
graham.reeds

2

La restituzione di 0 dovrebbe indicare al programmatore che il programma ha terminato correttamente il lavoro.


Restituendo 1 da main()segnali normalmente si è verificato un errore; restituendo 0 segnala successo. Se i tuoi programmi falliscono sempre, allora 1 è OK, ma non è la migliore idea.
Jonathan Leffler,

1
@JonathanLeffler: il significato del ritorno 1da mainè definito dall'implementazione. Gli unici valori definiti dalla lingua sono 0, EXIT_SUCCESS(spesso definito come 0), e EXIT_FAILURE. In OpenVMS, return 1;indica la chiusura corretta .
Keith Thompson,

VMS non è "normale", ai sensi di ciò che ho detto. Non è forse qualcosa come "qualsiasi valore strano è successo; anche i valori sono guasti 'su VMS?
Jonathan Leffler,

2

Omettere return 0

Quando un programma C o C ++ raggiunge la fine del maincompilatore genererà automaticamente il codice per restituire 0, quindi non è necessario inserire return 0;esplicitamente alla fine di main.

Nota: quando faccio questo suggerimento, è quasi invariabilmente seguito da uno dei due tipi di commenti: "Non lo sapevo". o "È un cattivo consiglio!" La mia logica è che è sicuro e utile fare affidamento sul comportamento del compilatore esplicitamente supportato dallo standard. Per C, dal C99; vedi ISO / IEC 9899: 1999 sezione 5.1.2.2.3:

[...] un ritorno dalla chiamata iniziale alla mainfunzione equivale a chiamare la exitfunzione con il valore restituito dalla mainfunzione come argomento; raggiungendo il }che termina la mainfunzione restituisce un valore di 0.

Per C ++, dal primo standard nel 1998; vedi ISO / IEC 14882: 1998 sezione 3.6.1:

Se il controllo raggiunge la fine di main senza incontrare un'istruzione return, l'effetto è quello dell'esecuzione di return 0;

Da allora tutte le versioni di entrambi gli standard (C99 e C ++ 98) hanno mantenuto la stessa idea. Facciamo affidamento sulle funzioni membro generate automaticamente in C ++ e poche persone scrivono return;dichiarazioni esplicite alla fine di una voidfunzione. Le ragioni per non omettere sembrano ridursi a "sembra strano" . Se, come me, sei curioso di sapere la logica della modifica dello standard C, leggi questa domanda . Si noti inoltre che nei primi anni '90 questa era considerata una "pratica sciatta" perché all'epoca era un comportamento indefinito (sebbene ampiamente supportato).

Inoltre, le Linee guida di base C ++ contengono più istanze di omissione return 0;alla fine maine nessuna istanza in cui è scritto un ritorno esplicito. Sebbene non ci sia ancora una linea guida specifica su questo particolare argomento in quel documento, sembra almeno un tacito appoggio alla pratica.

Quindi sostengo di ometterlo; altri non sono d'accordo (spesso con veemenza!) In ogni caso, se incontri un codice che lo omette, saprai che è esplicitamente supportato dallo standard e saprai cosa significa.


2
Questo è un cattivo consiglio perché i compilatori che implementano solo C89, non uno standard successivo, sono ancora estremamente comuni (scrivo questo nel 2017) e rimarranno estremamente comuni per il prossimo futuro. Ad esempio, l'ultima volta che ho controllato nessuna versione dei compilatori di Microsoft implementava C99, ed è mia comprensione che questo è ancora tipico per i compilatori di sistemi embedded che non sono GCC.
zwol,

4
@zwol: Chiunque non abbia altra scelta che usare un compilatore che è obsoleto da 28 anni probabilmente ha più problemi che decidere se includere esplicitamente return 0;, tuttavia noterei che molti compilatori di quell'epoca hanno implementato un implicito return 0;anche prima che lo fosse standardizzato.
Edward,

2
In realtà, lavoro molto su sistemi embedded e non ho incontrato un compilatore che non supporti implicitamente return 0da oltre un decennio. Anche le versioni correnti di Microsoft C lo supportano . Forse le tue informazioni non sono aggiornate?
Edward,

2
Posso apprezzare che questo sia controverso in C, quasi (per @zwol). In C ++ ogni controversia che circonda questo è pura assurdità.
Razze di leggerezza in orbita

2
@Edward Non ho detto che la controversia non esisteva, ho detto che era una sciocchezza: P
Razze di leggerezza in orbita

1

Cosa restituire dipende da cosa si desidera fare con l'eseguibile. Ad esempio, se si utilizza il programma con una shell della riga di comando, è necessario restituire 0 per un esito positivo e uno diverso da zero per l'errore. Quindi sarai in grado di usare il programma in shell con elaborazione condizionale a seconda del risultato del tuo codice. Inoltre è possibile assegnare qualsiasi valore diverso da zero in base alla propria interpretazione, ad esempio per errori critici diversi punti di uscita del programma potrebbero terminare un programma con valori di uscita diversi e disponibile per la shell chiamante che può decidere cosa fare controllando il valore restituito. Se il codice non è destinato all'uso con shell e il valore restituito non disturba nessuno, potrebbe essere omesso. Personalmente uso la firmaint main (void) { .. return 0; .. }


Il formato di main () è determinato dall'implementazione, che significa compilatore. Il programmatore non viene scelto quale modulo scegliere, tranne quando un compilatore supporta diversi moduli.
Lundin,

@Lundin Il tipo restituito verrà implementato dall'implementazione. Ma il valore che deve essere restituito è deciso dal programmatore. C99 Sezione 5.1.2.2.3 menziona che il tipo di reso di mainè compatibile con int. Pertanto, il ritorno intnon sarà un problema. Sebbene siano consentiti altri tipi di restituzione, in tal caso la variabile di ambiente con il valore restituito non sarà specificata. Ma se un programmatore lo fa return 0;in bash, può essere usato per creare rami.
phoxis,

1

Se hai davvero problemi legati all'efficienza della restituzione di un numero intero da un processo, probabilmente dovresti evitare di chiamare quel processo così tante volte che questo valore restituito diventa un problema.

Se lo stai facendo (chiama un processo così tante volte), dovresti trovare un modo per mettere la tua logica direttamente all'interno del chiamante, o in un file DLL, senza allocare un processo specifico per ogni chiamata; le allocazioni di processi multipli comportano in questo caso il problema di efficienza rilevante.

In dettaglio, se si desidera solo sapere se la restituzione di 0 è più o meno efficiente della restituzione di 1, in alcuni casi potrebbe dipendere dal compilatore, ma in generale, supponendo che siano letti dalla stessa fonte (locale, campo, costante, incorporato nel codice, risultato della funzione, ecc.) richiede esattamente lo stesso numero di cicli di clock.


1

Ecco una piccola dimostrazione dell'uso dei codici di ritorno ...

Quando si utilizzano i vari strumenti forniti dal terminale Linux, è possibile utilizzare il codice di ritorno, ad esempio, per la gestione degli errori dopo il completamento del processo. Immagina che sia presente il seguente file di testo myfile:

Questo è un esempio per verificare come funziona grep.

Quando si esegue il comando grep, viene creato un processo. Una volta che è passato (e non si è rotto) restituisce un codice tra 0 e 255. Ad esempio:

$ grep order myfile

Se fate

$ echo $?
$ 0

otterrai uno 0. Perché? Perché grep ha trovato una corrispondenza e ha restituito un codice di uscita 0, che è il solito valore per uscire con successo. Diamo un'occhiata di nuovo ma con qualcosa che non è all'interno del nostro file di testo e quindi non verrà trovata alcuna corrispondenza:

$ grep foo myfile
$ echo $?
$ 1

Poiché grep non è riuscito a far corrispondere il token "pippo" con il contenuto del nostro file, il codice di ritorno è 1 (questo è il solito caso in cui si verifica un errore, ma come detto sopra hai molti valori tra cui scegliere).

Ora il seguente script bash (semplicemente digitandolo in un terminale Linux) sebbene molto semplice dovrebbe dare un'idea della gestione degli errori:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

Dopo la seconda riga non viene stampato nulla sul terminale poiché "pippo" ha reso grep return 1 e controlliamo se il codice di ritorno di grep era uguale a 0. La seconda istruzione condizionale fa eco al suo messaggio nell'ultima riga poiché è vera a causa di CHECK == 1.

Come puoi vedere se stai chiamando questo e quel processo, a volte è essenziale vedere cosa ha restituito (dal valore restituito da main ()).


In uno script shell, useresti if grep foo myfile; then echo 'Match found'; else echo 'No match was found'; fi: testare direttamente lo stato di ritorno. Se si desidera acquisire lo stato (per la creazione di report, ecc.), Utilizzare un compito. È possibile utilizzare if grep foo myfile; CHECK=$?; [ "$CHECK" = 0 ]; then echo 'Match found'; else echo 'No match was found'; fio è possibile utilizzare tre righe. È inoltre possibile utilizzare le opzioni -se -qper grepimpedire la visualizzazione delle corrispondenze o dei messaggi di errore di routine. Tuttavia, si tratta di minutia di shell - il punto chiave, che può essere utile lo stato di uscita - è OK.
Jonathan Leffler,

1

Qual è il modo corretto (più efficiente) per definire la funzione main () in C e C ++ - int main () o void main () - e perché?

Quelle parole "(più efficiente)" non cambiano la domanda. A meno che non ci si trovi in ​​un ambiente indipendente, esiste un modo universalmente corretto per dichiarare main(), ed è come restituire int.

Cosa dovrebbe main()tornare in C e C ++?

Non è ciò che dovrebbe main() tornare, è ciò che main() ritorna. main()è, ovviamente, una funzione che qualcun altro chiama. Non hai alcun controllo sul codice che chiama main(). Pertanto, è necessario dichiarare main()con una firma di tipo corretto per abbinare il suo chiamante. Semplicemente non hai scelta in merito. Non devi chiederti cosa sia più o meno efficiente, o quale sia lo stile migliore o peggiore, o qualcosa del genere, perché la risposta è già perfettamente ben definita, per te, dagli standard C e C +. Seguili e basta.

Se int main () quindi restituisce 1 o restituisce 0?

0 per successo, diverso da zero per fallimento. Ancora una volta, non qualcosa che devi scegliere (o arrivare a): è definito dall'interfaccia a cui dovresti essere conforme.

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.