Ar trebui să returnez EXIT_SUCCESS sau 0 din main()? (Programare, C++, C, Valoare De Returnare, Principal)

Trevor Hickey a intrebat.

Este o întrebare simplă, dar tot văd răspunsuri contradictorii: ar trebui ca rutina principală a unui program C++ să returneze 0 sau EXIT_SUCCESS?

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

sau

int main(){return 0;}

Sunt exact același lucru? Ar trebui ca EXIT_SUCCESS să fie folosit numai cu exit()?

Am crezut că EXIT_SUCCESS ar fi o opțiune mai bună, deoarece alte programe ar putea considera zero ca fiind un eșec, dar am mai auzit că, dacă se returnează 0, compilatorul este capabil oricum să îl schimbe cu o valoare diferită.

Comentarii

  • Acest răspuns despre C90 parafrazează standardul — 0 și EXIT_SUCCESS sunt ambele interpretate ca succes. –  > Por ta.speot.is.
  • Răspund aici, deoarece simt că va mai citi cineva acest lucru în viitor. Practic, există mai multe paradigme despre cum arată „C-ul corect”. Unele paradigme preferă folosirea literaliilor în locul macrourilor, de exemplu, în loc să treacă NULL ca argument, pot trece (const char *)0 pentru a indica faptul că nu este doar un null, dar dacă nu era null, ar trebui să fie un pointer de caracter constant. Alte paradigme preferă să fie agnostice față de tipuri și, prin utilizarea macrotipurilor, pot evita să fie nevoite să își modifice baza de cod atunci când lucrurile se schimbă radical. De exemplu, multe – – –  > Por Dmitry.
  • @Dmitry <continued> definițiile tipurilor din API-ul Windows nu sunt corecte pe platformele mai noi, dar, deoarece erau macro-uri, au avut o modalitate ușoară de a schimba toate tipurile în cele care funcționează prin redefinirea macro-ului, iar o mare parte din aceste tipuri pur și simplu au fost scalate prin definiție (de exemplu, int este diferit pe diferite platforme). Pentru a rezuma, folosiți lucruri precum EXIT_SUCCESS dacă codul de returnare contează și se poate schimba în viitor, în caz contrar returnarea lui 0 poate părea un număr magic, dar aceasta este totuși o convenție standard perfect valabilă. codul de eroare este în principal pentru programe pentru a canaliza rezultatele numerice de la unul la altul, – – –  > Por Dmitry.
  • @Dmitry <continued> utilizarea codurilor de eroare pentru a vă depana programul este cam slabă, deoarece dacă returnează 0, este o informație destul de inutilă, cu excepția unor cazuri în care există erori neexploatate într-un program care pot face ca programul să se întrerupă în mod silențios și trebuie să verificați dacă a returnat normal(0) sau dacă a apărut o eroare silențioasă. Numărul return este mai util pentru a trece 0…255 de la un program la altul în funcție de intrările acestora, în rest nu există niciun motiv să vă gândiți la asta: fie returnează 0, fie folosiți un main precompilat care include un apel void „init” pentru a nu vă deranja vizual cu returnări inutile. –  > Por Dmitry.
  • @Dmitry de asemenea, merită menționat faptul că prin returnarea EXIT_SUCCESS, reduceți foarte mult ușurința de a verifica ce este returnul programului, deoarece dacă oamenii se uită în codul sursă principal și văd că returnează un macro, nu pot spune cu încredere că este 0 fără a merge la definiția lui EXIT_SUCCESS și a o verifica: ușor în unele editori, greu în altele. Dacă spuneți în documentația dvs. că returnează EXIT_SUCCESS este de-a dreptul inutil, deoarece oamenii nu știu ce este EXIT_SUCCESS decât dacă fac presupuneri, iar dacă faceți presupuneri cu privire la macro-uri, este posibil să vă înșelați cu privire la returnare, deoarece macro-urile pot varia…  > Por Dmitry.
8 răspunsuri
Keith Thompson

EXIT_FAILURE, fie într-o declarație de returnare în main fie ca argument pentru exit(), este singura modalitate portabilă de a indica un eșec într-un program C sau C++. exit(1) poate semnala de fapt o terminare cu succes pe VMS, de exemplu.

Dacă aveți de gând să utilizați EXIT_FAILURE atunci când programul dvs. eșuează, atunci ați putea la fel de bine să folosiți EXIT_SUCCESS atunci când reușește, doar de dragul simetriei.

Pe de altă parte, dacă programul nu semnalează niciodată eșecul, puteți utiliza fie 0 fie EXIT_SUCCESS. Ambele sunt garantate de standard pentru a semnala finalizarea cu succes. (Este foarte puțin posibil ca EXIT_SUCCESS ar putea avea o altă valoare decât 0, dar este egală cu 0 în toate implementările de care am auzit vreodată).

Utilizarea 0 are avantajul minor că nu aveți nevoie de #include <stdlib.h> în C, sau #include <cstdlib> în C++ (dacă folosiți un return în loc să apelați exit()) – dar pentru un program de dimensiuni semnificative, oricum veți include stdlib direct sau indirect.

De altfel, în C începând cu standardul din 1999 și în toate versiunile de C++, ajungând până la sfârșitul lui main() se face un apel implicit return 0; oricum, așa că s-ar putea să nu fie nevoie să folosiți nici 0 sau EXIT_SUCCESS în mod explicit. (Dar, cel puțin în C, eu consider că un explicit return 0; să fie un stil mai bun).

(Cineva a întrebat despre OpenVMS. Nu l-am mai folosit de mult timp, dar, din câte îmi amintesc, valorile de stare impare denotă în general succes, în timp ce valorile pare denotă eșec. Implementarea în C face o hartă 0 la 1, astfel încât return 0; indică o terminare cu succes. Celelalte valori sunt transmise neschimbate, deci return 1; indică, de asemenea, încheierea cu succes. EXIT_FAILURE ar avea o valoare pară diferită de zero).

Comentarii

  • @KeithThompson puteți să vă clarificați răspunsul în ceea ce privește VMS (OpenVMS?). Nu este clară relația EXIT_SUCCESS / EXIT_FAILURE cu 0 și 1. Aș explica, în schimb, valorile pare/impare. –  > Por malat.
  • @malat: Tu chiar folosești VMS? –  > Por Keith Thompson.
  • nu, nu l-am folosit niciodată. Căutam un răspuns canonic, deoarece wikipedia folosea un formulare diferită. –  > Por malat.
  • @Rhymoid: Acest lucru este specificat de C, nu de POSIX. –  > Por Keith Thompson.
  • @DeanP: 0 și EXIT_SUCCESS nu sunt garantate să aibă aceeași valoare (am menționat acest lucru în răspunsul meu), dar ambele denotă o terminare cu succes. EXIT_SUCCESS este mai bună din punct de vedere stilistic dacă utilizați și EXIT_FAILURE, dar exit(0) este în regulă. –  > Por Keith Thompson.
Alok Save

Nu contează. Ambele sunt la fel.

Citate standard C++:

În cazul în care valoarea statusului este zero sau EXIT_SUCCESS, se returnează o formă definită de implementare a statusului terminare cu succes.

Comentarii

  • Nu contează pentru compilator, dar poate conta ca o chestiune de stil. –  > Por celtschk.
  • @celtschk: Chestiunea de stil se bazează pe percepție a.k.a. Non Standardized, astfel încât nu contează ca o diferență. puteți compara doar mere cu mere, nu mere cu pere. –  > Por Alok Save.
  • Nu există nicio garanție că EXIT_SUCCESS == 0. Pe de altă parte, nu există niciun motiv întemeiat pentru care să nu fie. –  > Por Keith Thompson.
  • @PravasiMeet: Un sistem ar putea avea mai mult de o valoare care să indice succesul. –  > Por Keith Thompson.
  • Funcția mai presus de formă, dar claritatea mai presus de funcție. Pot să vă spun din experiența profesională că stilul contează foarte mult în programare. – user824425
James

0 este, prin definiție, un număr magic. EXIT_SUCCESS este aproape în mod universal egal cu 0, din fericire. Deci, de ce să nu returnezi/ieși pur și simplu 0?

exit(EXIT_SUCCESS); este foarte clar în ceea ce privește semnificația.

exit(0); pe de altă parte, este contraintuitiv în unele privințe. Cineva care nu este familiarizat cu comportamentul shell-urilor ar putea presupune că 0 == fals == rău, la fel ca orice altă utilizare a lui 0 în C. Dar nu – în acest caz special, 0 == succes == bun. Pentru majoritatea dezvoltatorilor experimentați, nu va fi o problemă. Dar de ce să îl punem în încurcătură pe cel nou fără niciun motiv?

tl;dr – dacă există o constantă definită pentru numărul tău magic, aproape niciodată nu există un motiv pentru a nu folosi constanta în primul rând. Este mai ușor de căutat, adesea mai clar etc. și nu vă costă nimic.

Comentarii

  • Cred că comentariile dvs. cu privire la faptul că oamenii se așteaptă ca 0 să fie în mod automat rău sunt deplasate. Foarte multe API-uri folosesc 0 pentru succes și non-0 pentru eșec, chiar și în stdlib. De exemplu, stdlib (fclose(), setvbuf(), …), POSIX (listen(), pthread_create(), pipe(), …), și multe altele, multe alte biblioteci (de exemplu, OpenGL [glGetError()], zlib [deflate()/inflate()/…], SDL [SDL_CreateWindowAndRenderer()/…], și altele). –  > Por Tim Čas.
  • Sigur, există și alte cazuri în care 0 este folosit pentru „succes”, dar are dreptate în ceea ce privește faptul că este confuz. –  > Por Paul Wintz.
Emilio Garavaglia

Aceasta este o poveste fără sfârșit care reflectă limitele (un mit) ale „interoperabilității și portabilității peste tot”.

Ceea ce ar trebui să returneze programul pentru a indica „succesul” ar trebui să fie definit de cel care primește valoarea (sistemul de operare sau procesul care a invocat programul), nu de o specificație de limbaj.

Dar programatorilor le place să scrie codul în „mod portabil” și, prin urmare, își inventează propriul model pentru conceptul de „sistem de operare” care definește valorile simbolice de returnat.

Acum, într-un scenariu de tip mulți-la-mulți (în care mai multe limbaje servesc la scrierea de programe pentru mai multe sisteme), corespondența dintre convenția limbajului pentru „succes” și cea a sistemului de operare (care nu poate fi garantată ca fiind întotdeauna aceeași) ar trebui să fie gestionată de implementarea specifică a unei biblioteci pentru o platformă țintă specifică.

Dar, din păcate, aceste concepte nu erau atât de clare în momentul în care limbajul C a fost implementat (în principal pentru a scrie nucleul UNIX), iar gigacalorii de cărți au fost scrise spunând că „return 0 înseamnă succes”, deoarece acest lucru era valabil pentru sistemele de operare din acel moment care aveau un compilator C.

De atunci încolo, nu s-a făcut niciodată o standardizare clară cu privire la modul în care trebuie tratată o astfel de corespondență. C și C++ au propria lor definiție a „valorilor de returnare”, dar nimeni nu a acordat o traducere adecvată pentru sistemul de operare (sau mai bine zis: nici o documentație a compilatorului nu spune nimic despre aceasta). 0 înseamnă succes dacă este adevărat pentru UNIX – LINUX și – din motive independente – și pentru Windows, iar acest lucru acoperă 90% din „computerele de consum” existente, care – în majoritatea cazurilor – nu iau în considerare valoarea de retur (astfel încât putem discuta zeci de ani, dar nimeni nu va observa niciodată!).

În cadrul acestui scenariu, înainte de a lua o decizie, puneți-vă aceste întrebări: – Sunt interesat să comunic ceva apelantului meu despre ceea ce există? (Dacă pur și simplu returnez întotdeauna 0 … nu există niciun indiciu în spatele întregului lucru) – Are apelantul meu convenții cu privire la această comunicare? (Rețineți că o singură valoare nu este o convenție: aceasta nu permite nicio reprezentare a informațiilor)

În cazul în care ambele răspunsuri sunt negative, probabil că soluția bună este să nu scrieți deloc declarația principală de returnare. (Și lăsați compilatorul să decidă, în funcție de obiectivul la care lucrează).

În cazul în care nu există convenții, 0=succes îndeplinește majoritatea situațiilor (iar utilizarea simbolurilor poate fi problematică, dacă acestea introduc o convenție).

În cazul în care există convenții, asigurați-vă că utilizați constante simbolice care sunt coerente cu acestea (și asigurați coerența convențiilor, nu coerența valorilor, între platforme).

Phonon

Odată ce începeți să scrieți cod care poate returna o multitudine de stări de ieșire, începeți să #define‘ing toate. În cazul de față EXIT_SUCCESS are sens în contextul în care nu este un „număr magic„. Acest lucru face codul mai ușor de citit, deoarece fiecare alt cod de ieșire va fi EXIT_SOMETHING. Dacă scrieți pur și simplu un program care se va întoarce când a terminat, return 0 este valabil și, probabil, chiar mai curat, deoarece sugerează că nu există o structură sofisticată a codului de returnare.

paulsm4

Ceea ce returnezi dintr-un program este doar o convenție.

Nu, nu mă pot gândi la nicio circumstanță în care „EXIT_SUCCESS” nu ar fi „0”.

Personal, aș recomanda „0”.

IMHO…

Comentarii

  • Programez în C++ de 10 ani și încă nu-mi amintesc dacă „0” înseamnă succes sau eșec în ceea ce privește valorile de returnare. –  > Por lahjaton_j.
  • @lahjaton_j Înțeleg. Cred că e din cauză că e contraintuitiv: 0 este fals, iar multe funcții returnează 0 la eșec/nu face nimic. –  > Por meaning-matters.
Mohammad Moghimi

Dacă folosiți EXIT_SUCCESS, codul dvs. va fi mai portabil.

http://www.dreamincode.net/forums/topic/57495-return-0-vs-return-exit-success/

Comentarii

  • Mă îndoiesc foarte mult că vă face codul mai mult sau mai puțin portabil. –  > Por Benjamin Lindley.
  • Nu, nu o va face. Standardul garantează că 0 și EXIT_SUCCESS indică o terminare cu succes. –  > Por Keith Thompson.
  • Dacă ați fi spus „Dacă utilizați EXIT_FAILURE, codul tău va fi mai portabil”, ar fi fost adevărat. –  > Por lopho.
Ambidextru

Unele compilatoare ar putea crea probleme cu acest lucru – pe un compilator Mac C++, EXIT_SUCCESS a funcționat bine pentru mine, dar pe un compilator Linux C++ a trebuit să adaug cstdlib pentru ca acesta să știe ce este EXIT_SUCCESS. În afară de asta, sunt unul și același lucru.

Comentarii

  • Am vrut să spun că pe un Mac EXIT_SUCCESS a funcționat fără a include cstdlib. –  > Por Ambidextru.
  • Dacă EXIT_SUCCESS a funcționat fără a include nici <stdlib.h> sau <cstdlib>, un alt antet trebuie să-l fi definit, direct sau indirect. În C++, este obișnuit ca anteturile standard să fie #include alte anteturi standard. Dacă acest lucru se compilează fără erori: int main() { return EXIT_SUCCESS; } atunci compilatorul dvs. este, probabil, eronat. –  > Por Keith Thompson.