why returning 0 on success?

Hi all,
I'm just curious to understand why some system calls, let's say mkdir(2), return 0 on success and a different value on error (while setting errno at the same time). In this way the coding pattern seems to be:

Code:
  error = mkdir(...);
  if( error ) return error;

while if the mkdir (and other calls) returns a non-zero value on success it could be rewritten as

Code:
  if( ! mkdir(.. ) ) //error

that seems to me more C-like. Can anybody explain me the rationale behind the above code pattern?

Thanks
 
Because platform portability of the code is more important then the beauty of C.
Zero is encoding-independent. If we wanted to store one(1) in a 32-bit integer word, the first question would be "big-endian word or little-endian word?", followed by "how long are the bytes composing a little-endian word?", while zero will always look the same. Also it needs to be expected that some people cast errno to char or short at some point, or even to float.
(int)((char)ENOLCK) is not ENOLCK when char is not at least 8-bit long (7-bit ASCII char machines are supported by UNIX), while (int)((char)0) is 0 independent of the architectural details of char.

Most userspace applications on the other hand, assuming that they bother to check the return values, will probably only be interested in whether an error occurred or not, instead of branching in dependence of the exact error code (you'll normally just call strerror() or strerror_r() to notify the user and continue the fallback path or abort() afterwards), so the error code encoding, or the mere existance of an error code itself (for example GNU doesn't have EPROCLIM for example, which would cause an error at compile time due to an unknown symbol in code) is not of much relevance to most applications.

It's in fact considered bad style by many people to not write down what you're comparing when branching for integers that are effective bools in C. The better way would be
Code:
if (mkdir(...) != EXIT_SUCCESS)
...
with EXIT_SUCCESS from stdlib.h

Furthermore, the way to are proposing it would not allow to return the exact error type without reading the errno global variable which is not thread safe.
 
You can not assume that EXIT_SUCCESS equals 0 on every platform, I think at least on VAX architecture with the VMS OS EXIT_SUCCESS is 1. Also I wouldn't use the EXIT_* constants anywhere else but arguments to the exit(3) C function.
 
kpa said:
You can not assume that EXIT_SUCCESS equals 0 on every platform, I think at least on VAX architecture with the VMS OS EXIT_SUCCESS is 1. Also I wouldn't use the EXIT_* constants anywhere else but arguments to the exit(3) C function.

That doesn't matter as long as apps return EXIT_SUCCESS on success
 
Exactly but my point is about using EXIT_* constants for other uses and making assumptions about their values. This piece of code will work in reverse if EXIT_SUCCESS happens to be non-zero:

Code:
if (mkdir(...) != EXIT_SUCCESS)
 
kpa said:
Exactly but my point is about using EXIT_* constants for other uses and making assumptions about their values. This piece of code will work in reverse if EXIT_SUCCESS happens to be non-zero:

Code:
if (mkdir(...) != EXIT_SUCCESS)

Not if mkdir() returns the same EXIT_SUCCESS. The code is compiled on the same system and thus uses the same definition of EXIT_SUCCESS. It doesn't matter what the 'real' value of EXIT_SUCCESS is.

You are correct if the code looked like this:
Code:
if ( mkdir(...) )
Then it depends what mkdir()'s definition of EXIT_SUCCESS is whether or not it's evaluated as true or false.
 
IMO, success code = 0 is better cus operation "success" is only one return value, while operation "error" can have many values (and they != 0)
 
Back
Top