Why return a negative errno? (e.g. return -EIO)
Another simple example:
if (wpa_s->mlme.ssid_len == 0)
return -EINVAL;
Why the unary minus? I开发者_C百科s this (usually) done for functions that return >0 on success and <(=)0 on failure, or is there some other reason?
First, this isn't really a C thing. You're looking at a function that is written in C for some purpose. The same conventions could be used in any language.
Back in my old Unix days, there was something of a convention that 0 meant success, a positive number meant minor problems, and a negative number meant some sort of failure. Therefore, there was also a sort of convention of if (foo() >= 0) { /* success of a sort */ }
.
This was doubtless related to Unix process return codes, where 0 was success.
That's basically the reasons. Lots of functions have lots of "good" positive results, so that leaves the negative values for error codes.
C / POSIX error codes are a bit "historically grown," so there's not much sense in trying to attribute too much rhyme or reason to them.
Many more modern languages throw exceptions for errors so that they don't have to hijack part of their possible response range for error codes. Of course there are trade-offs either way.
Your understanding is broadly correct. The obvious interpretation is the right one.
The standard convention is slightly different than your formula, however.
In Unix, a program that exits with 0 status tests as true or success to CLI-level utilities like the shell. In the library, -1
is usually an error return.
This leads to a general paradigm where >= 0
means good and < 0
means error. None of this is set in stone.
BTW, this might be classified as the sentinel pattern and you could call it a sentinel return. It's actually a combination of a sentinel "value" and an error code, and it's easier to type and easier to make thread-safe than returning an error code in one place and a sentinel value for error in another.
Wikipedia reports that a sentinel value is used to terminate a loop, but I would think that a function return would be a far more common instance. No one is precisely in charge of these definitions.
From an optimization perspective, using negative numbers allows Unix-based kernels to check for an error code using only one comparison instead of two.
Functions in the kernel frequently return error codes in place of pointers. This means that the error codes can't overlap with valid pointer addresses, so they'd basically have to be either the lowest unsigned values (>= 0)
or the highest ones (<= unsigned max)
.
Checking pointer values for NULL
and for error codes are extremely common operations, so it makes sense to optimize them.
Typically the bottom values < 0x8000
are NULL
and the top values are error codes (remember that -1
is stored as 0xff...ff
, the maximum possible unsigned value).
This means that you can use one comparison to check for each:
NULL
if x <= 0x8000
(true for 0 to 0x8000)
ERRNO
if x >= (unsigned long)(-MAX_ERRNO)
(true for -1 to -MAX_ERRNO)
You can see this happening in Linux's err.h file.
精彩评论