Rationale behind return 0 as default value in C/C++ - c++

Is there a reason why zero is used as a "default" function return value? I noticed that several functions from the stdlib and almost everywhere else, when not returning a proper number (e.g pow(), strcpy()) or an error (negative numbers), simply return zero.
I just became curious after seeing several tests performed with negated logic. Very confusing.
Why not return 1, or 0xff, or any positive number for that matter?

The rationale is that you want to distinguish the set of all the possible (negative) return values corresponding to different errors from the only situation in which all went OK. The simplest, most concise and most C-ish way to pursue such distinction is a logical test, and since in C all integers are "true" except for zero, you want to return zero to mean "the only situation", i.e. you want zero as the "good" value.
The same line of reasoning applies to the return values of Unix programs, but indeed in the tests within Unix shell scripts the logic is inverted: a return value of 0 means "true" (for example, look at the return value of /bin/true).

Originally, C did not have "void". If a function didn't return anything, you just left the return type in the declaration blank. But that meant, that it returned an int.
So, everything returned something, even if it didn't mean anything. And, if you didn't specifically provide a return value, whatever value happened to be in the register the compiler used to return values became the function's return value.
// Perfectly good K&R C code.
NoReturn()
{
// do stuff;
return;
}
int unknownValue = NoReturn();
People took to clearing that to zero to avoid problems.

In shell scripting, 0 represents true, where another number typically represents an error code. Returning 0 from a main application means everything went successfully. The same logic may be being applied to the library code.
It could also just be that they return nothing, which is interpreted as 0. (Essentially the same concept.)

Another (minor) reason has to do with machine-level speed and code size.
In most processors, any operation that results in a zero automatically sets the zero flag, and there is a very cheap operation to jump against the zero flag.
In other words, if the last machine operation (e.g., PUSH) got us to zero, all we need is a jump-on-zero or a jump-not-zero.
On the other hand, if we test things against some other value, then we have to move that value into the register, run a compare operation that essentially subtracts the two numbers, and equality results in our zero.

Because Bash and most other UNIX shell environments regard 0 as success, and -x as a system error, and x as a user-defined error.

There's probably a bunch of forgotten history dating back to the days when everything was written in asm. In general it is much easier to test for zero than for other specific values.

I may be wrong about this, but I think that it's mainly for historical reasons (hysterical raisins?). I believe that K&R C (pre-ANSI) didn't have a void type, so the logical way to write a function that didn't return anything interesting was to have it return 0.
Surely somebody here will correct me if I'm wrong... :)

My understanding is that it was related to the behaviour of system calls.
Consider the open() system call; if it is successful, it returns a non-negative integer, which is the file descriptor that was created. However, down at the assembler level (where there's a special, non-C instruction that traps into the kernel), when an error is returned, it is returned as a negative value. When it detects an error return, the C code wrapper around the system call stores the negated value into errno (so errno has a positive value), and the function returns -1.
For some other system calls, the negative return code at the assembler level is still negated and placed into errno and -1 is returned. However, these system calls have no special value to return, so zero was chosen to indicate success. Clearly, there is a large variety of system calls, but most manage to fit these conventions. For example, stat() and its relatives return a structure, but a pointer to that structure is passed as an input parameter, and the return value is a 0 or -1 status. Even signal() manages it; -1 was SIG_DFL and 0 was SIG_IGN, and other values were function pointers. There are a few system calls with no error return - getpid(), getuid() and so on.
This zero-indicates-success mechanism was then emulated by other functions which were not actually system calls.

Conventionally, a return code of 0 specifies that your program has ended normally and all is well. (You can remember this as "zero errors", although for technical reasons, you cannot use the number of errors your program found as the return code. See Style.) A return code other than 0 indicates that some sort of error has occurred. If your code terminates when it encounters an error, use exit, and specify a non-zero return code. Source

Because 0 is false and null in C/C++ and you can make handy short cuts when that happens.

It is because when used from a UNIX shell a command that returns 0 indicates success.
Any other value indicates a failure.
As Paul Betts indicates positive and negative values delimitate where the error probably originated, but this is only a convention and not an absolute. A user application may return a negative value without any bad consequence (other than it is indicating to the shell that the application failed).

Besides all the fine points made by previous posters, it also cleans up the code considerably when a function returns 0 on success.
Consider:
if ( somefunc() ) {
// handle error
}
is much cleaner than:
if ( !somefunc() ) {
// handle error
}
or:
if ( somefunc() == somevalue ) {
// handle error
}

Related

What is the convention for main function return values in C++?

I was reading sample code and found that for error messages they used return -1; and for the main function they used return 0;. However, when I substituted the main function return value to return 10000;, it still built and run with no errors. Does this mean that return values can be arbitrarily chosen and has no meaning for the computer (Excluding the case where you are using the return value for some user-defined operation)? What is the usual convention in assigning return values for different cases?
The return value from a main function (the application) can be used in other applications to indicate that how the program is terminated. Traditionally 0 is used if the program terminated successfully and other integers (negative or positive) indicates there were some problems or other conditions.
These are different from application to application and you can find these on their manuals to find what each return value means.
For example you can see grep command manual (http://www.gnu.org/software/grep/manual/html_node/Exit-Status.html) it states that exit value 0 is if a line has selected, 1 means no line has selected and 2 means there was an error
On systems that use libc, which is pretty much the majority of Unix systems, the following things happens when a program exits:
Functions registered with atexit or on_exit are called in reverse order
All open streams are closed, writing out any buffered output data
_exit is called, terminating the program
Only the low-order 8 bits of the exit status are kept, which truncates it to a value between 0 and 255. How the return status is treated depends on the parent process. For example, if the parent process was Bash, values between 0 and 127 are user-defined values, while 128+ are treated specially.
By convention a return value of 0 in main is often hint for the OS and users that the program was executed successfully. Other values can be used to represent different error codes or different paths of successful execution specific to the program. You can choose them freely.
For other functions in a program the interpretation of return values is up to the developer.
The portable return values are EXIT_SUCCESS, EXIT_FAILURE, and 0 (which returns the same value as EXIT_SUCCESS. Those manifest contacts are defined in <cstdlib>. The meanings of any other values are system-specific.
Returned value is specified by function definition:
ret function(params);
Then, any value of type ret will be accepted by the compiler.
Example:
int main();
Can return any value of type int (between -INT_MAX and +INT_MAX). Values outside this range can be automatically casted by the compiler. However, non int values (return std::vector<int>() for example) will lead to compiler errors.
Specifically, for the main function, you can return any value. Convention is to return 0 when no error occured, anything else when an error occured. Error values can be positive or negative, as you want.

Standard C functions: Check for -1 or 0?

Many standard C and POSIX functions return -1 for error, and 0 on success, for example truncate, fflush, msync, etc.
int ret = truncate("/some/file", 42);
Is it better practice to check for success with ret != -1 or ret == 0, and why?
My Thoughts
It's my experience most people check for the error case (ret != -1), as there is typically only one (consider functions that return NULL or EOF on error). However in hindsight, one could see these functions could benefit from returning errno directly (where 0 is considered no error).
There is also the worry that a function returns something other than 0 or -1, or that additional return values are later added. In these scenarios, it makes sense to test for the "tightest" range of values indicating success (ret == 0).
Update0
It's an assumption of mine that people are aware that EOF is typically defined as -1.
It depends on whether the function is a C standard library function or a POSIX function. C functions don't have a uniform standard for return codes so I'd use whatever test makes the most sense on a case-by-case basis.
POSIX, on the other hand, is more consistent. Almost all POSIX functions are defined to return -1 with a more specific error code available in errno. Some functions simply return 0 for success, while others have a multitude of success values. For example, open() returns file descriptors, read() returns the number of bytes read, etc.
For consistency I like to always use the same test when invoking POSIX functions: don't test for success, test for failure. POSIX functions that today return -1 upon error will always return exactly -1, so I would use one of two checks for all of them:
if (ret == -1) {
perror(...);
}
// or
if (ret < 0) {
perror(...);
}
(I prefer the first one but the second more general one doesn't bother me.)
In my opinion, it really depends on what you need to do and the range of return values.
Take a call with one success value and many failure values. It's generally easier to == or != against the successful return value than check against any failure values. In this case, you would test against != success if you need to, say, log and return or throw in case of a failure.
In a call with one and one, the desired behavior is more important, so I suggest choosing the more readable. If your codes needs to react to and possibly return on failure, then check for == failure instead of != success. The former is more readable, since it takes one step of thinking and the failure constant may be helpfully named.
You may also want to consider which is more likely and handle that first, or which is numerically greater or lesser.
In your case, with two functions sharing a success code and with differing failure codes, it falls to whichever seems more readable. I would agree that testing for == 0 in both cases would seem better, but it really depends on how much code comes between the calls. If you have a few dozen lines, there might not be much of a difference in readability. If it's very close, you might even be able to OR the results together and save yourself a few more steps.
Comparing the man pages for truncate and fflush, both return 0 on success, but return different values for error (truncate -> -1, fflush -> EOF). So I'd check for 0.
Cert guidelines seem to prefer the '!= 0' check as is valid in many of their example code snippets.
Always check the man pages for return codes.
Usually 0 means success, but exceptions exist such as printf().
Check man 2 intro for errnos and error codes of system calls.
Whatever you do, never ever shortcut a test for success with
if (!ret)
It's confusing and someone (including yourself) will misread it later as a test for failure. It's generally better to use explicit tests.
If the definition is that 0 means success, and you want to check for success then you should check equivalence to 0. (and this is for no other reason than shear readability)
For most POSIX API functions, negative values are errors. So I'd test for failure with if (ret < 0).
My rule of thumb is that functions like these return the error code (or just whether an error occurred) through the return value. So, for me it makes sense that a return value of 0 means that there was nothing of that sort to return and that no error occurred. Therefore I just check if the return value was 0 if I want to test whether the function was successful, and if not just check what the error value was and deal with it accordingly.

Coding conventions for method returns in C++

I have observed that the general coding convention for a successful completion of a method intended functionality is 0. (As in exit(0)).
This kind of confuses me because, if I have method in my if statement and method returns a 0, by the "if condition" is false and thereby urging me to think for a minute that the method had failed. Of course I do know I have to append with a "!" (As in if(!Method()) ), but isn't this convention kind of self contradicting itself ??
You need to differentiate between an error code and an error flag. A code is a number representing any number of errors, while a flag is a boolean that indicates success.
When it comes to error codes, the idea is: There is only one way to succeed, but there are many ways to fail. Take 0 as a good single unique number, representing success, then you have every other number is a way of indicating failure. (It doesn't make sense any other way.)
When it comes to error flags, the idea is simple: True means it worked, false means it didn't. You can usually then get the error code by some other means, and act accordingly.
Some functions use error codes, some use error flags. There's nothing confusing or backwards about it, unless you're trying to treat everything as a flag. Not all return values are a flag, that's just something you'll have to get used to.
Keep in mind in C++ you generally handle errors with exceptions. Instead of looking up an error code, you just get the necessary information out of the caught exception.
The convention isn't contradicting itself, it's contradicting your desired use of the function.
One of them has to change, and it's not going to be the convention ;-)
I would usually write either:
if (Function() == 0) {
// code for success
} else {
// code for failure
}
or if (Function() != 0) with the cases the other way around.
Integers can be implicitly converted to boolean, but that doesn't mean you always should. 0 here means 0, it doesn't mean false. If you really want to, you could write:
int error = Function();
if (!error) {
// code for success
} else {
// code for failure, perhaps using error value
}
There are various conventions, but most common for C functions is to return 0 on failure and a positive value on success so you can just use it inside an if statement (almost all CPUs have conditional jumps which can test whether a value is 0 or not which is why in C this "abused" with 0 meansing false and everything else meaning true).
Another convention is to return -1 on error and some other value on success instead (you especially see this with POSIX functions that set the errno variable). And this is where 0 can be interpreted as "success".
Then there's exit. It is different, because the value returned is not to be interpreted by C, but by a shell. And here the value 0 means success, and every other value means an error condition (a lot of tools tell you what type of error occurred with this value). This is because in the shell, you normally only have a range of 0-127 for returning meaningful values (historic reasons, it's a unsigned byte and everything above 127 means killed by some signal IIRC).
You have tagged your question as [c] and [c++]. Which is it? Because the answer will differ somewhat.
You said:
I have observed that the general coding convention for a successful completion of a method intended functionality is 0.
For C, this is fine.
For C++, it decidedly is not. C++ has another mechanism to signal failure (namely exceptions). Abusing (numeric) return values for that is usually a sign of bad design.
If exceptions are a no-go for some reasons, there are other ways to signal failure without clogging the method’s return type. Alternatives comprise returning a bool (consider a method try_insert) or using an invalid/reserved return value for failure, such as string::npos that is used by the string::find method when no occurrence is found in the string.
exit(0) is a very special case because it's a sentinel value requesting that the compiler tell the operating system to return whatever the real success value is on that OS. It's entirely possible that it won't be the number 0.
As you say, many functions return 0 for success, but they're mainly "legacy" C library OS-interfacing functions, and following the interfacing style of the operating system's on which C was first developed and deployed.
In C++, 0 may therefore be a success value when wrapping such a C legacy interface. Another situation where you might consider using 0 for success is when you are effectively returning an error code, such that all errors are non-zero values and 0 makes sense as a not-an-error value. So, don't think of the return value as a boolean (even though C++ will implicitly convert it to one), but as an error code where 0 means "no error". (In practice, using an enum is typically best).
Still, you should generally return a boolean value from functions that are predicates of some form, such as is_empty(), has_dependencies(), can_fit() etc., and typically throw an exception on error. Alterantively, use a sub-system (and perhaps thread) specific value for error codes as per libc's errno, or accept a separate reference/pointer argument to the variable to be loaded with the error code.
int retCode = SaveWork();
if(retCode == 0) {
//Success !
} else if(retCode == ERR_PERMISSIONS) {
//User doesn't have permissions, inform him
//and let him chose another place
} else if(retCode == ERR_NO_SPACE) {
//No space left to save the work. Figure out something.
} else {
//I give up, user is screwd.
}
So, if 0/false were returned to mean failure, you could not distinguish what was the cause of the error.
For C++, you could use exceptions to distinguish between different errors. You could also use
a global variable, akin to errno which you inspect in case of a failure. When neither exceptions or global variables are desired, returning an error code is commonly used.
As the other answers have already said, using 0 for success leaves everything non-zero for failure. Often (though not always) this means that individual non-zero values are used to indicate the type of failure. So as has already been said, in that situation you have to think of it as an error code instead of an success/failure flag.
And in that kind of situation, I absolutely loathe seeing a statement like if(!Method()) which is actually a test for success. For myself too, I've found it can cause a moment of wondering whether that statement is testing for success or failure. In my opinion, since it's not a simple boolean return, it shouldn't be written like one.
Ideally, since the return is being used as an error code the author of that function should have provided an enum (or at least a set of defines) that can be used in place of the raw numbers. If so, then I would always prefer the test rewritten as something like if(Method() == METHOD_SUCCESS). If the author didn't provide that but you have documentation on the error code values, then consider making your own enum or defines and using that.
If nothing else, I would write it as if(Method() == 0) because then at least it should still be clear to the reader that Method doesn't return a simple boolean and that zero has a specific meaning.
While that convention is often used, it certainly isn't the only one. I've seen conventions that distinguish success and failure by using positive and negative values. This particularly happens when a function returns a count upon success, but needs to returns something that isn't a value count upon failure (often -1). I've also seen variations using unsigned numbers where (unsigned int)-1 (aka 0xffffffff) represented an error. And there are probably others that I can't even think of offhand.
Since there's no single right way to do it, various authors at various times have invented various schemes.
And of course this is all without mentioning that exceptions offer (among other things) a totally different way to provide information when a function has an error.
I use this convention in my code:
int r = Count();
if(r >= 0) {
// Function successful, r contains a useful non-negative value
}
else {
// A negative r represents an error code
}
I tend to avoid bool return values, since they have no advantages (not even regarding their size, which is rounded to a byte) and limits possible extensions of the function's return values.
Before using exceptions, take into account the performance and memory issues they bring.

Why do we follow opposite conventions while returning from main()?

I have gone through this and this,
but the question I am asking here is that why is 0 considered a Success?
We always associate 0 with false, don't we?
Because there are more fail cases than success cases.
Usually, there is only one reason we succeed (because we're successful :)), but there are a whole lot of reasons why we could fail. So 0 means success, and everything else means failure, and the value could be used to report the reason.
For functions in your code, this is different, because you are the one specifying the interface, and thus can just use a bool if it suffices. For main, there is one fixed interface for returns, and there may be programs that just report succeed/fail, but others that need more fine error reporting. To satisfy them all, we will have multiple error cases.
I have to quibble with with Johannes' answer a bit. True 0 is used for success because there is only 1 successful outcome while there can be many unsuccessful outcomes. But my experience is that return codes have less to do with reasons for failure than levels of failure.
Back in the days of batch programming there were usually conventions for return codes that allowed for some automation of the overall stream of execution. So a return code of 4 might be a warning but the next job could continue; an 8 might mean the job stream should stop; a 12 might mean something catastrophic happened and the fire department should be notified.
Similarly, batches would set aside some range of return codes so that the overall batch stream could branch. If an update program returned XX, for instance, the batch might skip a backup step because nothing changed.
Return codes as reasons for failure aren't all that helpful, certainly not nearly as much as log files, core dumps, console alerts, and whatnot. I have never seen a system that returns XX because "such and such file was not found", for instance.
Generally the return values for any given program tend to be a list (enum) of possible values, such as Success or specific errors. As a "list", this list generally tends to start at 0 and count upwards. (As an aside, this is partly why the Microsoft Error Code 0 is ERROR_SUCCESS).
Globally speaking, Success tends to be one of the only return values that almost any program should be capable of returning. Even if a program has several different error values, Success tends to be a shared necessity, and as such is given the most common position in a list of return values.
It's just the simplest way to allow a most common return value by default. It's completely separate from the idea of a boolean.
Here's the convention that I'm used to from various companies (although this obviously varies from place to place):
A negative number indicates an error occured. The value of the negative number indicates (hopefully) the type of error.
A zero indicates success (generic success)
A positive number indicates a type of success (under some business cases there various things that trigger a successful case....this indicates which successful case happened).
I, too, found this confusing when I first started programming. I resolved it in my mind by saying, 0 means no problems.

Why default return value of main is 0 and not EXIT_SUCCESS?

The ISO 1998 c++ standard specifies that not explicitly using a return statement in the main is equivalent to use return 0.
But what if an implementation has a different standard "no error" code, for example -1?
Why not use the standard macro EXIT_SUCCESS that would be replaced either by 0 or -1 or any other value depending on the implementation?
C++ seems to force the semantic of the program, which is not the role of a language which should only describe how the program behaves. Moreover the situation is different for the "error" return value: only EXIT_FAILURE is a standard "error" termination flag, with no explicit value, like "1" for example.
What are the reasons of these choices?
Returning zero from main() does essentially the same as what you're asking. Returning zero from main() does not have to return zero to the host environment.
From the C90/C99/C++98 standard document:
If the value of status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned.
Actually, return 0 won't necessarily return 0! I'm quoting the C standard here, because it's what I know best.
About return in main():
5.1.2.2.3 Program termination
If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument;
About exit():
7.20.4.3 The exit function
Synopsis
#include <stdlib.h>
void exit(int status);
[...]
Finally, control is returned to the host environment. If the value of status is zero or
EXIT_SUCCESS, an implementation-defined form of the status successful termination is
returned.
The standard is simply making a determination on what must be the value when not explicitly set. It is up to the developers to either explicitly set the return value or assume an appropriate semantic for the default. I don't think the language is trying to force any semantics on to the developers.
0 is the standard (success) exit code on all POSIX systems, and all systems I know! I think it has been this way sinc time begain (or at least since Unix did...) So it's for this reason I would say.
What system do you know that is different?
0 as the return code for success, and postive integers as errors is the standard in C and Unix. This scheme was chosen because normally one doesn't care why a program succeeded, just that it did. On the other hand, there are lots of ways for a program to fail with an error, and one is often interested in this information. Hence it makes sense to use a scalar value for success, and a range of values for error. Using positive integers is a memory-saving C convention, as they allow the error code to be defined as an unsigned int.
OS/360 and successors use a numeric exit code, 0 usually being success, 4 for warnings (such as a compiler that generated warning message), 8 for error, and 12 for especially bad errors
(such as being unable to open SYSPRINT, the standard output unit).
Computer language standards say what a program written in the language has to do, and what will happen. In this case, the C and C++ standards say that returning 0 signals success, among other things.
Language implementations allow programs to run on particular implementations. It's the job of the implementor to figure out how to make I/O work according to the standard, or to give the OS the correct result code.
What a program does and what the OS sees do not have to be the same thing. All that is necessary is that the program works as the standard says on the given OS.
By browsing cstdlib I ended up with two lines:
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
So EXIT_SUCCESS equals 0, and EXIT_FAILURE equals 1, which means it doesn't matter, thought.
Checked on Linux (OpenSuse) and ended up with the same thing.
If you were also thinking about why the error code for success is 0 instead of any other value, I would add that it might have been historically for performance reasons, as comparing with 0 have been sightly faster (I think in modern architectures might be the same as with any number) and usually you don't check for a particular error code, just if it was success or any error (so it makes sense to use the fastest comparison for that).