Sign in to follow this  

stupid question.. what's "return 0"?

This topic is 4482 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Return is an exit statement: it tells the programme to leave the current function.

Share this post


Link to post
Share on other sites
return exits from a function and makes the funciton give a value back to whatever called it.

For example, in:
int Add(int Num1, int Num2)
{
return Num1 + Num2;
}
Add is a function that gives back an integer that equals Num1 and Num2 added together. You could use it like:
int Sum;
Sum = Add(3, 2);

Now Sum will have 5, becase that is what add passed back

Share this post


Link to post
Share on other sites
return 0 is generally, but not always, an error, or a false condition. Take for example this code:
int isBaseballExciting()
{
return 0;
}

The function can be used in if conditionals.
if (isBaseballExciting())
{
WatchTheGame();
}
else
{
TurnOnAquaTeenHungerForceDVD();
}

Share this post


Link to post
Share on other sites
Unforunately, sometimes return 0 also indicates that there is no problem, such as with the main function. Almost as if the query was "IsThereAProblem()" or "DidTheFunctionFail()" so that "return 0" indicates that there was no problem.

Share this post


Link to post
Share on other sites
Quote:
Original post by Inmate2993
return 0 is generally, but not always, an error, or a false condition.

Actually, C and C++ idiom is to consider return 0 a successful completion. This stems from Unix command line utility idiom, where a program that terminates successful generates no output to the terminal.

Your example is rooted in "old" C idiom, and definitely not C++ idiom because of the presence of the bool type in C++ and C99. In fact, your example is dependent, in C++ and C99, on the promotion of zero integral values to false (and non-zero values to true).

Share this post


Link to post
Share on other sites
Quote:
Original post by Oluseyi
Your example is rooted in "old" C idiom, and definitely not C++ idiom because of the presence of the bool type in C++ and C99. In fact, your example is dependent, in C++ and C99, on the promotion of zero integral values to false (and non-zero values to true).

So you would recommend returning 0 for success? I find that a bit misleading, and have been using return 1 for that very reason, that it makes more sense that way. Care to explain to me exactly why we shouldn't rely on something that is in fact in the standards? (I do believe it is standard that 0 gets evaluated as false, and anything else as true?) Or, on the other hand, correct me if I am direly wrong, as I would hate to be doing something for reasons that are not in fact good ones.

Share this post


Link to post
Share on other sites
You are partially right. Many functions in the STL return 0 upon success. And so do many in other APIs and Libraries. However, when used in an if statement, 1 DOES evaluate to true and 0 and under to false. So this:

int a = 1;
int b = 0;
int c = 3;

bool all = a && b && c;

would be

all = false;


However,

bool all = a || b || c;

would be true.

Back to the normal topic:


return


well, returns something. main() returns 0, meaning success. Lets say we want to multiply something, but using a function. It would be:

int Multiply(int foo, int bar) // its an int because it will return an int
{
return foo * bar; // it will return foo times bar
}

int main() // main
{
int foobar = Multiply(13, 13); // foobar would get the return
// of multiply, or 13 * 13,
// or 169

return 0; // success
}


-DBZ-

Share this post


Link to post
Share on other sites
If you only need two discretee codes then that's the natural thing to do, but then you should really use a boolean type and named true/false constants too.

However using 0 as a sign of success has a few advantages. For instance you often want multiple error codes but only one error code, in which case 0 is the natural choice since it can easily be distinguished from the rest. This is how the return code from main works.
When you both need multiple positive and negative return codes it's common to return negative values for errors and positive ones otherwise (including zero), again this is because it's so easy to separate the two sets and negative "success" codes would've been unintuitive. This is how Microsoft's HRESULTS work for instance.
Additionally some libraries return string constants containing the error messages themselves instead of integer codes in which case 0 (NULL) is the only real choice left.

Share this post


Link to post
Share on other sites
Quote:
Original post by SirLuthor
So you would recommend returning 0 for success?


I recommend choosing one convention and sticking with it. Personally, I use a non-zero value to indicate an error since there can be more than one type of error yet there is typically only one type of success! An alternative strategy is the following:

#define SUCCESS 1
#define FAIL_DISK 2
#define FAIL_IO 3
...

#define SUCCEEDED(x) ((x) == SUCCESS)
#define FAILED(x) ((x) != SUCCESS)
...

if (SUCCEEDED(DoSomething())) { return 0; }

In my opinion, the lack of good error handling is one of the most difficult issues to overcome in C. I wish the language itself had better support for them!

Share this post


Link to post
Share on other sites
It seems to me that using 0 as a sign of success forces a change of semantics so that the question becomes "is there a failure" rather than "is there a success".

Share this post


Link to post
Share on other sites
Quote:
Original post by mnansgar
I use a non-zero value to indicate an error since there can be more than one type of error yet there is typically only one type of success! An alternative strategy is the following:

#define SUCCESS 1
#define FAIL_DISK 2
#define FAIL_IO 3[/code]
I admit that it's a micro-optimization but most libraries have chosen to use 0 because it's generally more efficient to detect than other values. This can make quite a difference when using error handling through codes extensively (consider the Win32 API where EVERYTHING can fail).
But, as you say, the most important thing is that you're internally consistent.
Quote:
Original post by LessBread
It seems to me that using 0 as a sign of success forces a change of semantics so that the question becomes "is there a failure" rather than "is there a success".
Perhaps.. But it's a common convention, you get used to it after a while.
There really isn't much of an alternative if you need multiple failure
and/or success codes.

Share this post


Link to post
Share on other sites
It seems to me that one way to get used to it is to change how you think about return values, specifically about what they mean (ie. semantics). I think the HRESULT example is a good one because it illustrates how to take return values to the next level.

Share this post


Link to post
Share on other sites
Quote:
Original post by LessBread
It seems to me that one way to get used to it is to change how you think about return values, specifically about what they mean (ie. semantics). I think the HRESULT example is a good one because it illustrates how to take return values to the next level.

Alternatively, don't use return value to indicate success/failure. Use them for process results, and use a different mechanism like exceptions for error handling. This way, you're not forced to have all your functions have return values just as a means of indicating proper completion.

Share this post


Link to post
Share on other sites
Quote:
Original post by SirLuthor
So you would recommend returning 0 for success?

I would recommend using a more robust error handling mechanism, unless you're limited to C, which I never use (anymore). I realize not everyone has this luxury, so I won't make any Grand Pronouncements on how you should perform your error handling: pick a convention and stick to it, but realize that if your code is to be reused by others, it probably helps to use the convention that is predominant in the target environment. If you're writing a library for Win32, use HRESULTs; if you're writing a Unix library, use return 0 for success.

Share this post


Link to post
Share on other sites
As for the microoptimisation I'm pretty sure 0 is no different to detect than any other value on x86 since there is no compare-to-zero instruction - you always have to use cmp eax,something to check a return code. The only way it would be an optimisation would be if you used or eax,eax (or and eax,eax) to detect zero and since that is a smaller instruction than cmp eax,0 this allowed your inner loop to fit in cache.

Share this post


Link to post
Share on other sites
Quote:
Original post by ZQJ
As for the microoptimisation I'm pretty sure 0 is no different to detect than any other value on x86 since there is no compare-to-zero instruction - you always have to use cmp eax,something to check a return code. The only way it would be an optimisation would be if you used or eax,eax (or and eax,eax) to detect zero and since that is a smaller instruction than cmp eax,0 this allowed your inner loop to fit in cache.
Yup, although you'd generally use TEST EAX,EAX since it doesn't update the register (throwing of any further dependencies on it).
Additionally if the constant is a result of some earlier calculation you'll often have the flags updated for free (the zero or sign flags are particularily useful), some systems even update the flags simply by loading a value into a register so you don't necessarily need to perform arithmetic on an error code to use it.
So if you need three distinct error values (+1, 0 and -1) it's probably to check whether the value is more or less than zero rather than testing for +1 or -1 explicitly.

Share this post


Link to post
Share on other sites
I think it all depends on your style. Generally, if your function needs to return a value indicating success/failure, you would just return boolean true or false. But if your function is more complex than simply true/false, you would use a table of success/failure type constants; kSuccess = 0, kError1, kError2, kError3, etc.

Share this post


Link to post
Share on other sites
That's what happens after 20+ years of programming build up with no industry standard and multiple vendors and so on.

Share this post


Link to post
Share on other sites
no it really isn't. The main purpose of putting return in a function is to exit out of the function, and also to return a useful value, as in the Add function written above.

Using return to help handle errors is a little trick that a lot of people use because it is convient. However you shouldn't let it get too complex, as return really isn't meant for that kind of thing. I personally never use exceptions, but if I needed to do a lot of error checking I would use exceptions, because that is what they are designed for.

So I recommend that you forget all about return statements being used to deal with errors. View the one in main as a magic line of code that has no purpose, because in most situations it doesn't.

Share this post


Link to post
Share on other sites
Quote:
Original post by infernosnow
woah, this thing got way more responces than I expected... "Return" is really this stinking complex? o_0

return isn't complex; using return intelligently and consistently is.

Share this post


Link to post
Share on other sites
Quote:
Original post by dudedbz1
You are partially right. Many functions in the STL return 0 upon success. And so do many in other APIs and Libraries. However, when used in an if statement, 1 DOES evaluate to true and 0 and under to false. So this:


No, 0 evaluates to false and any other value, positive or negative, evaluates to true.

Quote:
Original post by infernosnow
woah, this thing got way more responces than I expected... "Return" is really this stinking complex? o_0


return is easy. It simply puts a value on the stack to be read by the calling function, or in the case of main() the program that started the application, usually the Operating System.

How people have chosen to use return is what makes it complex.

Theres really no reason to use return codes unless you have to, or its really the best solution. Error indication is a poor excuse when you have access to exceptions. If exceptions were available, then its usually a sign of lazy programming and/or lack of understanding how to use exceptions properly.

IMO, return should only be used to return whatever value is defined by its opperation, unless it is a function specifically designed to return an error code only.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ravyne
return is easy. It simply puts a value on the stack to be read by the calling function, or in the case of main() the program that started the application, usually the Operating System.


On the stack? I suppose the float stack, but otherwise eax and edx are typically used for return values (on x86).


Share this post


Link to post
Share on other sites
Quote:

No, 0 evaluates to false and any other value, positive or negative, evaluates to true.

Really? I thought under was false and over was true. I'm sorry, I didnt know :(

I just said that cuz SDL_Init(...); would return -1 when it fails.

Share this post


Link to post
Share on other sites
Sign in to follow this