I previously read that 0 in C-Language refers to false while 1 is true.
And have noticed that the main function returns 0 but why is that? in case all of my code ran successfully it should return true (1).
Another related question, I still can't understand who can use the returnable value? since no other function called the main function inside my program so nothing can know if my program ran well or not.
I am a little bit confused.
Your logic would make sense if the return value of main were interpreted as a Boolean value, but it isn't. Returning from the initial call to main is like calling the exit function: It reports a termination status to the system you're running on.
Standard C specifies 3 portable exit statuses:
0, indicating success
EXIT_SUCCESS, also indicating success
EXIT_FAILURE, indicating failure
(The last two are macros defined in <stdlib.h>.)
On Unix, any 8-bit value (0 .. 255) is allowed. All non-zero values are interpreted as error codes. There is no universal convention for what any given number means, just that 0 represents success and anything else some kind of failure.
As for who can use the return value: On Unix, a parent process can use wait or waitpid to get the exit status of a terminated child.
In the C standard library, functions that perform an action generally don't return a true/false status. (Tests such as islower or isdigit do, but they don't have any other effects.) For example, remove (which deletes a file) returns 0 on success and -1 on error. This is also a common pattern with Unix system calls. For exmple, open returns a file descriptor (a non-negative integer) on success and -1 on error.
It's essentially what #Brandon already said in the comments.
main is supposed to return the exit/error code of the program. In the Unix convention, 0 is used to indicate no error (the error value is "false"). And then positive values are used for indicating that there is an error and what error it was.
It's really just about the kind of question you ask a program when it finish.
Case 1:
Did you fail?
Case 2:
Did you pass?
In the first case a "good program" will return false (aka zero)
In the second case a "good program" will return true (aka non-zero).
Consensus is to use Case 1, i.e. "Did you fail?". Therefore a non-failing program returns zero to say "I did not fail".
The benefit of this approach is that non-zero values can be used to expressed different kind of failures while zero is alway "no failure"
There's a difference between what the C language considers true (non-zero) or false (zero) and what value(s) the operating system uses to indicate a normal program termination.
To be strictly correct, C programs should exit with a code of either EXIT_SUCCESS for normal program termination or EXIT_FAILURE for abnormal termination. EXIT_SUCCESS will map to whatever code the underlying platform uses to indicate success, which may or may not be 0.
Related
This question already has answers here:
Return Code on failure. Positive or negative?
(6 answers)
Closed 4 years ago.
Either I didn't searched well or this question is obvious.
In c, the main function returns what You want. But since Posix gives the example, 0 is for success and other values are for fail (mostly positive values in Linux).
Based on this assumption, I have seen a practive where all other functions in the code have the same behaviour.
Pros:
practical because you can return the result of your call directly as the result of your main
Cons:
0 becomes OK, 1 becomes KO.
I am sure it is not good, but I have here 2 million lines based on that.
Is that common ? Does it have a name ?
Returning 0 for success is common. There is no specific name for such behavior.
This is what the C standard says:
7.22.4.4 The exit function
...
2. The exit function causes normal program termination to occur.
...
5. 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. If the value of status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.
Most functions that returns a handle, such as OpenProcess, OpenFile, OpenThread, FindWindow, etc, return 0 upon failure. I understand that return an invalid result to indicate failure is a good practice. However, if windows choose -1 to be the INVALID_HANDLE_VALUE, why don't these functions return -1 upon failure?
There are many conjectures you can make, but yes the reasons are historical and due to compatibility in the process of porting old 16bits code to newer one.
Some functions originally returned -1 when failing, in the respect of C habit to return negative values on failure.
Moving to new 32bits versions, for the reason of compatibility mentioned above, lead to the creation of INVALID_HANDLE_VALUE equated to -1.
But because the handles sometimes were real pointers, and for the simplicity of comparison for NULL value many new functions were designed to return NULL on failure.
One interesting point is that INVALID_HANDLE_VALUE happens to be numerically equal to the pseudohandle returned by GetCurrentProcess(). So using an invalid handle in some functions could lead to valid results or terrible deadlocks as in the case of INVALID_HANDLE_VALUE used in a call to WaitForSingleObject. This will lead to an endless wait for the current process.
You can find the whole story, told from the authors, here https://blogs.msdn.microsoft.com/oldnewthing/20040302-00/?p=40443
I'm writing a module which exports an interface similar to send and recv.
Since those functions are supposed to return respectively the number of sent and received bytes, I cannot do proper error management as I would do normally (i.e. using enumeratives and returning mnemonic values).
In a situation like this should I set errno as the standard library does? If so, since errno is thread specific, is there a particular way of writing on it, or can I simply assign a value to it?
Edit: experimenting it I noticed that setting errno by assignment is working. Still: is this safe and portable for any system?
This is a bit old, but errno - manual section 3 says that you can directly assign to it, even though it is a macro, and it will be thread local
Not only can you set errno, in many cases you should set errno. When calling some library functions you can only reliably detect an error if you first set errno to zero. See strtol for an example.
From the POSIX specification of strtol:
[CX] [Option Start] The strtol() function shall not change the setting of errno if successful.
Since 0, {LONG_MIN} or {LLONG_MIN}, and {LONG_MAX} or {LLONG_MAX} are returned on error and are also valid returns on success, an application wishing to check for error situations should set errno to 0, then call strtol() or strtoll(), then check errno. [Option End]
Actually, you probably can do "proper" (as you put it) error management since you return an int.
Just use non-negative values for the number of bytes read or written and negative values for error codes. You don't have to limit yourself to -1:
enum myerrors {
ERR_NO_MEMORY = -1,
ERR_BAD_ARGS = -2,
ERR_CPU_EXPLODED = -3,
// and so on
};
However, setting errno in the fashion you want is valid. The standard states that errno expands to a modifiable lvalue, meaning you can set it. From C1x/n1425, 7.5 Errors <errno.h>:
... and errno which expands to a modifiable lvalue that has type int, the value of which is set to a positive error number by several library functions.
You can just assign a value to errno, but keep in mind that there are other ways to signal an error which, depending on your situation, may be more suitable:
Do not return the number of bytes read, but instead have an output parameter with type int * (or size_t * or whatever you use). You can then return an error code.
Assuming that your return type is a signed type and that a negative sent or received amount of bytes does not make sense, use negative values to signal the respective error conditions.
Yes, you can assign to it, and yes, the assignment will be thread-safe. See Is errno thread-safe?
From: http://support.sas.com/documentation/onlinedoc/sasc/doc700/html/lr1/errno.htm
The only portable values for errno are EDOM and ERANGE
So that answers your portability question.
I came across an is_equals() function in a c API at work that returned 1 for non-equal sql tables (false) and 0 for equal ones (true). I only realized it after running test cases on my code, one for the positive example and one for the negative and they both failed which at first made little sense. The code in the API does not have a bug as the output was recorded correctly in its documentation.
My questions - are there upside down worlds / parallel universes / coding languages where this logical NOTing is normal? Isn't 1 usually true? Is the coder of the API making an error?
It is common for comparison functions to return 0 on "equals", so that they can also return a negative number for "less than" and a positive number for "greater than". strcmp() and memcmp() work like this.
It is, however, idiomatic for zero to be false and nonzero to be true, because this is how the C flow control and logical boolean operators work. So it might be that the return values chosen for this function are fine, but it is the function's name that is in error (it should really just be called compare() or similar).
This upside-down-world is common with process error returns. The shell variable $? reports the return value of the previous program to execute from the shell, so it is easy to tell if a program succeeds or fails:
$ false ; echo $?
1
$ true ; echo $?
0
This was chosen because there is a single case where a program succeeds but there could be dozens of reasons why a program fails -- by allowing there to be many different failure error codes, a program can determine why another program failed without having to parse output.
A concrete example is the aa-status program supplied with the AppArmor mandatory access control tool:
Upon exiting, aa-status will set its return value to the
following values:
0 if apparmor is enabled and policy is loaded.
1 if apparmor is not enabled/loaded.
2 if apparmor is enabled but no policy is loaded.
3 if the apparmor control files aren't available under
/sys/kernel/security/.
4 if the user running the script doesn't have enough
privileges to read the apparmor control files.
(I'm sure there are more widely-spread programs with this behavior, but I know this one well. :)
I suspect it's just following the Linux / Unix standard for returning 0 on success.
Does it really say "1" is false and "0" is true?
There's no good reason for 1 to be true and 0 to be false; that's just the way things have always been notated. So from a logical perspective, the function in your API isn't "wrong", per se.
That said, it's normally not advisable to work against the idioms of whatever language or framework you're using without a damn good reason to do so, so whoever wrote this function was probably pretty bone-headed, assuming it's not simply a bug.
It may very well be a mistake on the original author, however the notion that 1 is true and 0 is false is not a universal concept. In shell scripting 0 is returned for success, and any other number for failure. In other languages such as Ruby, only nil and false are considered false, and any other value is considered true, so in Ruby both 1 and 0 would be considered true.
Simple Answer
0 = false
1 = true
I'm not sure if I'm answering the question right, but here's a familiar example:
The return type of GetLastError() in Windows is nonzero if there was an error, or zero otherwise. The reverse is usually true of the return value of the function you called.
Generally we think that 0 is false and 1 is true
Another simple example:
if (wpa_s->mlme.ssid_len == 0)
return -EINVAL;
Why the unary minus? Is 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.