Reputation: 118480
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?
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
).
It's an assumption of mine that people are aware that EOF
is typically defined as -1
.
Upvotes: 5
Views: 1579
Reputation: 4378
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.
Upvotes: 2
Reputation: 361585
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.)
Upvotes: 8
Reputation: 283614
For most POSIX API functions, negative values are errors. So I'd test for failure with if (ret < 0)
.
Upvotes: 1
Reputation: 26586
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.
Upvotes: 0
Reputation: 48247
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.
Upvotes: 3
Reputation: 67831
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.
Upvotes: 2
Reputation: 25497
Cert guidelines seem to prefer the '!= 0' check as is valid in many of their example code snippets.
Upvotes: 2
Reputation: 77034
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)
Upvotes: 1
Reputation: 1503
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.
Upvotes: 3