ChatGPT解决这个技术问题 Extra ChatGPT

Should I return EXIT_SUCCESS or 0 from main()?

It's a simple question, but I keep seeing conflicting answers: should the main routine of a C++ program return 0 or EXIT_SUCCESS?

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

or

int main(){return 0;}

Are they the exact same thing? Should EXIT_SUCCESS only be used with exit()?

I thought EXIT_SUCCESS would be a better option because other software may want to deem zero as failure, but I also heard that if you return 0, the compiler is capable of changing it to a different value anyway.

This answer about C90 paraphrases the standard -- 0 and EXIT_SUCCESS are both interpreted as success.
I'll respond here since I feel somebody else will be reading this in the future. Basically there are many paradigms on what "correct C" looks like. Some paradigms prefer using literals over macros, for example, instead of passing NULL as an argument, they may pass (const char *)0 to indicate that it is not just a null, but if it wasn't null, it should be a constant character pointer. Other paradigms prefer being type agnostic and by using macro types, they can avoid needing to change their codebase when things radically change. For example, many -
@Dmitry Windows API type definitions are not correct in newer platforms, but since they were macros, they had easy way to change all the types to those that do work by redefining the macro, and much of these types simply scaled by definition(eg. int is different on different platforms). To summarize, use things like EXIT_SUCCESS if the return code matters and may change in the future, otherwise returning 0 may seem like a magic number but that's still perfectly valid standard convention. error code is mostly for programs to pipe number results from one to another, -
@Dmitry using error codes to debug your program is kinda weak since if it does return 0, it's pretty useless information except in some cases when there are unthrown unhandled errors in a program that can make the program break silently, and you need to check if it returned normally(0) or a silent error occured. The number return is more useful for piping 0..255 from one program to another based on their inputs, otherwise there's no reason to think about it: either return 0 or use a precompiled main that inlines a void "init" call not to visually annoy you with useless return.
@Dmitry also worth noting that by returning EXIT_SUCCESS, you greatly reduce ease of checking what program return is because if people look into your main source code and see that it returns a macro, they can't confidently say that it is 0 without going to the definition of EXIT_SUCCESS and checking it: easy in some editors, hard in others. Saying in your documentation that it returns EXIT_SUCCESS is downright useless because people don't know what EXIT_SUCCESS is unless they make assumptions, and making assumptions on macros makes it possible to be wrong about the return since macros can vary

K
Keith Thompson

EXIT_FAILURE, either in a return statement in main or as an argument to exit(), is the only portable way to indicate failure in a C or C++ program. exit(1) can actually signal successful termination on VMS, for example.

If you're going to be using EXIT_FAILURE when your program fails, then you might as well use EXIT_SUCCESS when it succeeds, just for the sake of symmetry.

On the other hand, if the program never signals failure, you can use either 0 or EXIT_SUCCESS. Both are guaranteed by the standard to signal successful completion. (It's barely possible that EXIT_SUCCESS could have a value other than 0, but it's equal to 0 on every implementation I've ever heard of.)

Using 0 has the minor advantage that you don't need #include <stdlib.h> in C, or #include <cstdlib> in C++ (if you're using a return statement rather than calling exit()) -- but for a program of any significant size you're going to be including stdlib directly or indirectly anyway.

For that matter, in C starting with the 1999 standard, and in all versions of C++, reaching the end of main() does an implicit return 0; anyway, so you might not need to use either 0 or EXIT_SUCCESS explicitly. (But at least in C, I consider an explicit return 0; to be better style.)

(Somebody asked about OpenVMS. I haven't used it in a long time, but as I recall odd status values generally denote success while even values denote failure. The C implementation maps 0 to 1, so that return 0; indicates successful termination. Other values are passed unchanged, so return 1; also indicates successful termination. EXIT_FAILURE would have a non-zero even value.)


How is it even possible to implement POSIX utilities for OpenVMS when exit(0) is mapped to exit status 1? (if I understand your last paragraph correctly)
@Rhymoid: This is specified by C, not POSIX.
@DeanP: 0 and EXIT_SUCCESS are not guaranteed to have the same value (I mentioned that in my answer), but they both denote successful termination. EXIT_SUCCESS is stylistically better if you're also using EXIT_FAILURE, but exit(0) is ok.
This is personal (for same motive: explicit), but I like to "return(0)" (or != 0) because shell script "$?" compatibility (the majority unix programs return "$?"=0 for success).
@AndréA.G.Scotá: POSIX guarantees EXIT_SUCCESS==0. (And you don't need parentheses on a return statement. Personally, I think they make it look too much like a function call.)
A
Alok Save

It does not matter. Both are the same.

C++ Standard Quotes:

If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned.


It does not matter to the compiler, but it may matter as a matter of style.
@celtschk: Matter of style is perception based a.k.a Non Standardized so that does not count as an difference.You can only compare Apples with Apples not Apples with Pears.
There is no guarantee that EXIT_SUCCESS == 0. On the other hand, there's no good reason for it not to be.
@PravasiMeet: A system might have more than one value that indicates success.
Function over form, but clarity over function. I can tell you from professional experience that style matters a great deal in programming.
J
James

0 is, by definition, a magic number. EXIT_SUCCESS is almost universally equal to 0, happily enough. So why not just return/exit 0?

exit(EXIT_SUCCESS); is abundantly clear in meaning.

exit(0); on the other hand, is counterintuitive in some ways. Someone not familiar with shell behavior might assume that 0 == false == bad, just like every other usage of 0 in C. But no - in this one special case, 0 == success == good. For most experienced devs, not going to be a problem. But why trip up the new guy for absolutely no reason?

tl;dr - if there's a defined constant for your magic number, there's almost never a reason not to used the constant in the first place. It's more searchable, often clearer, etc. and it doesn't cost you anything.


I think your comments about people expecting 0 to be automatically bad is off the mark. Very many APIs use 0 for success, and non-0 for failure, even in the stdlib. E.g. stdlib (fclose(), setvbuf(), ...), POSIX (listen(), pthread_create(), pipe(), ...), and many, many other libraries (e.g. OpenGL [glGetError()], zlib [deflate()/inflate()/...], SDL [SDL_CreateWindowAndRenderer()/...], and more).
Sure, there are other instances where 0 is used for 'success,' but he's right about it being confusing.
d
danglingpointer

This is a never ending story that reflect the limits (an myth) of "interoperability and portability over all".

What the program should return to indicate "success" should be defined by who is receiving the value (the Operating system, or the process that invoked the program) not by a language specification.

But programmers likes to write code in "portable way" and hence they invent their own model for the concept of "operating system" defining symbolic values to return.

Now, in a many-to-many scenario (where many languages serve to write programs to many system) the correspondence between the language convention for "success" and the operating system one (that no one can grant to be always the same) should be handled by the specific implementation of a library for a specific target platform.

But - unfortunatly - these concept where not that clear at the time the C language was deployed (mainly to write the UNIX kernel), and Gigagrams of books where written by saying "return 0 means success", since that was true on the OS at that time having a C compiler.

From then on, no clear standardization was ever made on how such a correspondence should be handled. C and C++ has their own definition of "return values" but no-one grant a proper OS translation (or better: no compiler documentation say anything about it). 0 means success if true for UNIX - LINUX and -for independent reasons- for Windows as well, and this cover 90% of the existing "consumer computers", that - in the most of the cases - disregard the return value (so we can discuss for decades, bu no-one will ever notice!)

Inside this scenario, before taking a decision, ask these questions: - Am I interested to communicate something to my caller about my existing? (If I just always return 0 ... there is no clue behind the all thing) - Is my caller having conventions about this communication ? (Note that a single value is not a convention: that doesn't allow any information representation)

If both of this answer are no, probably the good solution is don't write the main return statement at all. (And let the compiler to decide, in respect to the target is working to).

If no convention are in place 0=success meet the most of the situations (and using symbols may be problematic, if they introduce a convention).

If conventions are in place, ensure to use symbolic constants that are coherent with them (and ensure convention coherence, not value coherence, between platforms).


P
Phonon

Once you start writing code that can return a myriad of exit statuses, you start #define'ing all of them. In this case EXIT_SUCCESS makes sense in context of not being a "magic number". This makes your code more readable because every other exit code will be EXIT_SOMETHING. If you simply write a program that will return when it's done, return 0 is valid, and probably even cleaner because it suggests that there's no sophisticated return code structure.


p
paulsm4

What you return from a program is just a convention.

No, I can't think of any circumstances where "EXIT_SUCCESS" wouldn't be "0".

Personally, I'd recommend "0".

IMHO...


I have been programming C++ for 10 years and still can't remember if 0 means success or failure in terms of return values.
@lahjaton_j I understand. It think it's because it's counter intuitive: 0 is false, and many functions return 0 on failure/doing nothing.
e
einpoklum

tl;dr: You could just not return anything.

It is ok (Bjarne Stroustrup says so...) to not-explicitly-return anything from the main() function. The compiler will take care things if your OS expects a return value.

This is not to detract from the discussion in the answers by @KeithThompson or @EmilioGaravaglia regarding the case of different possible return value, and being aware of how your program's return value gets interpreted etc.


M
Mohammad Moghimi

If you use EXIT_SUCCESS, your code will be more portable.

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


I highly doubt that it makes your code any more or any less portable.
No, it won't. The standard guarantees that 0 and EXIT_SUCCESS both denote successful termination.
If you had said "If you use use EXIT_FAILURE, your code will be more portable", it would be true.
A
Ambidextrous

Some compilers might create issues with this - on a Mac C++ compiler, EXIT_SUCCESS worked fine for me but on a Linux C++ complier I had to add cstdlib for it to know what EXIT_SUCCESS is. Other than that, they are one and the same.


I meant on a Mac EXIT_SUCCESS worked without including cstdlib.
If EXIT_SUCCESS worked without including either <stdlib.h> or <cstdlib>, some other header must have defined it, directly or indirectly. In C++, it's common for standard headers to #include other standard headers. If this compiles without error: int main() { return EXIT_SUCCESS; } then your compiler is probably buggy.