Devo restituire EXIT_SUCCESS o 0 da main ()?


124

È una domanda semplice, ma continuo a vedere risposte contrastanti: dovrebbe la routine principale di un programma C ++ restituire 0oEXIT_SUCCESS ?

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

o

int main(){return 0;}

Sono esattamente la stessa cosa? DovrebberoEXIT_SUCCESS essere usato solo con exit()?

Ho pensato che EXIT_SUCCESSsarebbe stata un'opzione migliore perché altri software potrebbero voler considerare zero come errore, ma ho anche sentito che se torni 0, il compilatore è in grado di cambiarlo comunque con un valore diverso.


Questo risponde alla tua domanda? stackoverflow.com/questions/1188335/...
Blastfurnace

2
Questa risposta su C90 parafrasa lo standard 0e EXIT_SUCCESSsono entrambe interpretate come successo.
ta.speot

Risponderò qui poiché sento che qualcun altro lo leggerà in futuro. Fondamentalmente ci sono molti paradigmi su come appare la "C corretta". Alcuni paradigmi preferiscono utilizzare i valori letterali rispetto alle macro, ad esempio, invece di passare NULL come argomento, possono passare (const char *) 0 per indicare che non è solo un null, ma se non era null, dovrebbe essere un puntatore a carattere costante. Altri paradigmi preferiscono essere indipendenti dal tipo e, utilizzando i tipi macro, possono evitare di dover cambiare la loro base di codice quando le cose cambiano radicalmente. Ad esempio, molti -
Dmitry

@Dmitry <continuo> Le definizioni dei tipi di API di Windows non sono corrette nelle piattaforme più recenti, ma poiché erano macro, avevano un modo semplice per cambiare tutti i tipi in quelli che funzionano ridefinendo la macro e molti di questi tipi sono semplicemente ridimensionati per definizione (es. int è diverso su piattaforme diverse). Per riassumere, usa cose come EXIT_SUCCESS se il codice di ritorno è importante e potrebbe cambiare in futuro, altrimenti restituire 0 potrebbe sembrare un numero magico ma è comunque una convenzione standard perfettamente valida. il codice di errore è principalmente per i programmi che convogliano i risultati dei numeri l'uno nell'altro, -
Dmitry

@Dmitry <continuo> l'utilizzo di codici di errore per eseguire il debug del programma è un po 'debole poiché se restituisce 0, sono informazioni piuttosto inutili tranne in alcuni casi quando ci sono errori non gestiti non eliminati in un programma che possono interrompere il programma silenziosamente, e ne hai bisogno per verificare se è tornato normalmente (0) o si è verificato un errore silenzioso. Il numero returnèpiù utile per convogliare 0..255 da un programma a un altro in base ai loro input, altrimenti non c'è motivo di pensarci: o restituisci 0 o usa un main precompilato che integra una chiamata void "init" a non visivamente infastidirti con inutili ritorni.
Dmitry

Risposte:


151

EXIT_FAILURE, sia in un'istruzione return in mainche come argomento a exit(), è l'unico modo portabile per indicare un errore in un programma C o C ++. exit(1)può effettivamente segnalare una terminazione riuscita su VMS, ad esempio.

Se intendi utilizzare EXIT_FAILUREquando il tuo programma fallisce, allora potresti anche usareEXIT_SUCCESS quando ha successo, solo per motivi di simmetria.

D'altra parte, se il programma non segnala mai un errore, è possibile utilizzare 0o EXIT_SUCCESS. Entrambi sono garantiti dallo standard per segnalare il completamento con successo. (È appena possibile cheEXIT_SUCCESS possa avere un valore diverso da 0, ma è uguale a 0 su ogni implementazione di cui abbia mai sentito parlare.)

L'utilizzo 0ha il vantaggio minore che non è necessario #include <stdlib.h>in C o #include <cstdlib>in C ++ (se si utilizza returnun'istruzione invece di chiamareexit() ), ma per un programma di dimensioni significative includerai stdlib direttamente o indirettamente Comunque.

Del resto, in C che inizia con lo standard del 1999 e in tutte le versioni di C ++, il raggiungimento della fine di main()fa return 0;comunque un implicito , quindi potresti non aver bisogno di usare nessuno dei due 0o EXIT_SUCCESSesplicitamente. (Ma almeno in C, considero uno stile esplicito return 0;migliore.)

(Qualcuno ha chiesto informazioni su OpenVMS. Non lo uso da molto tempo, ma poiché ricordo che i valori di stato dispari generalmente denotano successo mentre i valori pari denotano fallimento. L'implementazione del C si associa 0a 1, quindi ciò return 0;indica una terminazione riuscita. Altri valori vengono passati invariati , quindi return 1;indica anche una terminazione riuscita. EXIT_FAILUREavrebbe un valore pari diverso da zero.)


@KeithThompson potresti chiarire la tua risposta riguardo a VMS (OpenVMS?). Non è chiara la relazione EXIT_SUCCESS / EXIT_FAILURE con 0 e 1. Spiegherei invece i valori pari / dispari.
malat

@malat: Utilizzi effettivamente VMS?
Keith Thompson

no, non l'ho mai usato. Stavo cercando una risposta canonica, poiché wikipedia utilizzava una formulazione diversa .
malat

1
@Rhymoid: questo è specificato da C, non da POSIX.
Keith Thompson

1
@DeanP: 0e EXIT_SUCCESSnon è garantito che abbiano lo stesso valore (l'ho menzionato nella mia risposta), ma entrambi denotano una terminazione riuscita. EXIT_SUCCESSè stilisticamente migliore se usi anche tu EXIT_FAILURE, ma exit(0)va bene.
Keith Thompson,

25

Non importa. Entrambi sono la stessa cosa.

Citazioni standard C ++:

Se il valore dello stato è zero o EXIT_SUCCESS, viene restituita una forma definita dall'implementazione della terminazione riuscita dello stato.


12
Non ha importanza per il compilatore, ma può essere importante per una questione di stile.
celtschk

2
@celtschk: la questione dello stile è basata sulla percezione, ovvero non standardizzata, quindi non conta come differenza.Puoi confrontare solo mele con mele e non mele con pere.
Alok Save

3
Non vi è alcuna garanzia che EXIT_SUCCESS == 0. D'altra parte, non c'è nessuna buona ragione per non esserlo.
Keith Thompson

@KeithThompson: perché non c'è alcuna garanzia che EXIT_SUCCESS == 0.? Per favore spiegalo più chiaramente.
Distruttore

2
@PravasiMeet: un sistema potrebbe avere più di un valore che indica il successo.
Keith Thompson

11

0 è, per definizione, un numero magico. EXIT_SUCCESS è quasi universalmente uguale a 0, abbastanza fortunatamente. Allora perché non solo ritorno / uscita 0?

uscita (EXIT_SUCCESS); è abbondantemente chiaro nel significato.

exit (0); d'altra parte, è controintuitivo per certi versi. Qualcuno che non ha familiarità con il comportamento della shell potrebbe presumere che 0 == falso == cattivo, proprio come ogni altro uso di 0 in C. Ma no - in questo caso speciale, 0 == successo == buono. Per gli sviluppatori più esperti, non sarà un problema. Ma perché inciampare il nuovo ragazzo senza alcun motivo?

tl; dr - se c'è una costante definita per il tuo numero magico, non c'è quasi mai un motivo per non usare la costante in primo luogo. È più ricercabile, spesso più chiaro, ecc. E non ti costa nulla.


Penso che i tuoi commenti sulle persone che si aspettano che 0 sia automaticamente negativo non siano nel segno. Molte API usano 0 per il successo e non 0 per il fallimento, anche nello stdlib. Ad esempio stdlib ( fclose(), setvbuf(), ...), POSIX ( listen(), pthread_create(), pipe(), ...), e molti, molti altri librerie OpenGL (per esempio [ glGetError()], zlib [ deflate()/ inflate()/ ...], SDL [ SDL_CreateWindowAndRenderer()/ ...], e Di Più).
Tim Čas

2
Certo, ci sono altri casi in cui 0 viene utilizzato per "successo", ma ha ragione sul fatto che sia confuso.
Paul Wintz

10

Questa è una storia infinita che riflette i limiti (un mito) di "interoperabilità e portabilità su tutto".

Ciò che il programma dovrebbe restituire per indicare "successo" dovrebbe essere definito da chi riceve il valore (il sistema operativo o il processo che ha invocato il programma) non da una specifica del linguaggio.

Ma ai programmatori piace scrivere codice in "modo portabile" e quindi inventano il proprio modello per il concetto di "sistema operativo" definendo valori simbolici da restituire.

Ora, in uno scenario molti-a-molti (dove molti linguaggi servono a scrivere programmi su molti sistemi) la corrispondenza tra la convenzione linguistica per il "successo" e quella del sistema operativo (che nessuno può garantire che sia sempre la stessa) dovrebbe essere gestito dall'implementazione specifica di una libreria per una specifica piattaforma di destinazione.

Ma - sfortunatamente - questi concetti non erano così chiari al momento in cui il linguaggio C è stato distribuito (principalmente per scrivere il kernel UNIX), e gigagrammi di libri dove scritti dicendo "return 0 significa successo", dal momento che questo era vero sul sistema operativo a quella volta con un compilatore C.

Da quel momento in poi, non è mai stata fatta una chiara standardizzazione sul modo in cui tale corrispondenza dovrebbe essere gestita. C e C ++ hanno la propria definizione di "valori di ritorno" ma nessuno garantisce una corretta traduzione del sistema operativo (o meglio: nessuna documentazione del compilatore dice nulla al riguardo). 0 significa successo se vero per UNIX - LINUX e -per ragioni indipendenti- anche per Windows, e questo copre il 90% dei "computer consumer" esistenti, che - nella maggior parte dei casi - ignorano il valore restituito (quindi possiamo discutere per decenni, ma nessuno se ne accorgerà mai!)

All'interno di questo scenario, prima di prendere una decisione, poni queste domande: - Sono interessato a comunicare qualcosa al mio chiamante sulla mia esistenza? (Se restituisco sempre 0 ... non c'è alcun indizio dietro a tutto) - Il mio chiamante ha convenzioni su questa comunicazione? (Nota che un singolo valore non è una convenzione: ciò non consente alcuna rappresentazione delle informazioni)

Se entrambe le risposte sono no, probabilmente la buona soluzione è non scrivere affatto l'istruzione return principale. (E lascia che sia il compilatore a decidere, rispetto alla destinazione su cui sta lavorando).

Se non sono presenti convenzioni 0 = il successo soddisfa la maggior parte delle situazioni (e l'uso di simboli può essere problematico, se introducono una convenzione).

Se esistono convenzioni, assicurarsi di utilizzare costanti simboliche coerenti con esse (e garantire la coerenza delle convenzioni, non la coerenza dei valori, tra le piattaforme).


4

Una volta che inizi a scrivere codice che può restituire una miriade di stati di uscita, inizi #definetutti. In questo caso EXIT_SUCCESSha senso nel contesto di non essere un " numero magico ". Questo rende il tuo codice più leggibile perché ogni altro codice di uscita lo sarà EXIT_SOMETHING. Se scrivi semplicemente un programma che tornerà quando sarà finito, return 0sarà valido e probabilmente anche più pulito perché suggerisce che non esiste una sofisticata struttura del codice di ritorno.


0

Quello che ritorni da un programma è solo una convenzione.

No, non riesco a pensare a nessuna circostanza in cui "EXIT_SUCCESS" non sarebbe "0".

Personalmente, consiglierei "0".

A PARER MIO...


1
Ho programmato C ++ per 10 anni e ancora non riesco a ricordare se 0 significa successo o fallimento in termini di valori di ritorno.
lahjaton_j

@lahjaton_j ho capito. Pensa che sia perché è controintuitivo: 0è falso e molte funzioni ritornano 0in caso di fallimento / non fare nulla.
significato conta


-5

Alcuni compilatori potrebbero creare problemi con questo: su un compilatore C ++ per Mac, EXIT_SUCCESS ha funzionato bene per me, ma su un compilatore C ++ Linux ho dovuto aggiungere cstdlib per sapere cosa è EXIT_SUCCESS. Oltre a questo, sono la stessa cosa.


Intendevo che su un Mac EXIT_SUCCESS funzionava senza includere cstdlib.
Ambidestro

4
Se EXIT_SUCCESSlavorato senza includere uno <stdlib.h>o l'altro <cstdlib>, qualche altro header deve averlo definito, direttamente o indirettamente. In C ++, è comune per le intestazioni standard ad #includealtre intestazioni standard. Se viene compilato senza errori: int main() { return EXIT_SUCCESS; }probabilmente il tuo compilatore è difettoso.
Keith Thompson
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.