Reputation: 1720
I know EXIT_SUCCESS
/EXIT_FAILURE
is typically used for main() exit to indicate the successfulness of a program.
But is it also used (commonly or suggested) for normal function returns? I'm trying to write some "standard" code so wondering if I should use them instead of 0 or -1..
Upvotes: 6
Views: 4383
Reputation: 5629
EXIT_SUCCESS is a simbolic constant.-
You can use EXIT_SUCCESS
and EXIT_FAILURE
as well as 0 for OK and non 0 for failure.
Depends on taste, you can also make this
#define WRONG 1
#define COOL 0
and return those.-
Use whatever you feel more comfortable with, but keep your selection all the way.
Hope this helps!
Upvotes: 0
Reputation: 273406
Do no use EXIT_SUCCESS
or EXIT_FAILURE
for functions, or for anything other than exit
calls for that matter.
Feel free, however, to define your own types for your functions to return, but that depends on the situation and the exact code you're writing.
Some common approaches are:
enum
, one of which is your error, and check for that.As long as you are consistent, don't stray away from the conventions too far, and document everything, you should be OK.
Upvotes: 13
Reputation: 23367
You should never use EXIT_SUCCESS
or EXIT_FAILURE
outside of the context of a call to exit()
or the return value to main()
. The values of these integers are not specified by the standard, so you cannot write portable code if you assume that they are 0 or 1 respectively.
The standard does specify that exit(0)
and a return 0
from main()
behave the same way as exit(EXIT_SUCCESS)
and return EXIT_SUCCESS
, but these values are "special" in that they are to be interpreted in an implementation defined manner. That is, the actual value passed to the system may not be 0, and the constant value of EXIT_SUCCESS
is free to not be 0 if the implementation desires, so long as return 0
from main and return EXIT_SUCCESS
from main behave the same way.
If you use these values in your functions, your callers will have to compare against EXIT_SUCCESS
directly to determine if the function succeeded, which personally speaking I would find very inconvenient.
int MyFunction1 () { /* ... */ return EXIT_SUCCESS; }
int MyFunction2 () { /* ... */ return 0; }
// Portable:
if (MyFunction1 () == EXIT_SUCCESS) { ... }
if (MyFunction2 () == 0) { ... }
if (!MyFunction2 ()) { ... }
// Not portable:
if (MyFunction1 () == 0) { ... }
if (!MyFunction1 ()) { ... }
if (MyFunction2 () == EXIT_SUCCESS) { ... }
The problem becomes more obvious with EXIT_FAILURE
:
int MyFunction1 () { /*... */ return EXIT_FAILURE; }
// Not portable
if (MyFunction1 ()) { ... }
if (MyFunction1 () == 1) { ... }
// The only way to make this portable.
if (MyFunction1 () == EXIT_FAILURE) { ... }
Upvotes: 4
Reputation:
I don't use the EXIT_* macros for functions because:
Now, we come to main():
Upvotes: 0
Reputation: 77193
Many of the functions defined by the POSIX standard return 0 for success or a non-zero error code to indicate failure.
A lot of POSIX functions are defined to return 0 for success, -1 for failure and set errno global variable to indicate what failed. But a global errno doesn't work well in a multi-threaded program.
Upvotes: 3
Reputation: 59973
If you're using error codes, using the same constants for success that your libraries use makes things clearer.
Upvotes: 1