So apparently, in gcc/C, a compiler compiles when
if ((x=0)){ some code }
is used, while when
if (x=0){ some code }
is used, then compiler refuses to compile.
What are the differences between two?
As a note, I know what is the difference between x==0
and x=0
. I am just exploring how C behaves when met with some weird codes.
if(x!=0) means "if x is not 0", so that is evaluated comparing x to 0. That might also involve an implicit conversion.
Always do this. >#endif. >What is '0' and how is it 'defined'?! It is the successor to -1, and is defined using the piano axioms. In C, zero is false.
They are both same. The advantage of using (0==x) is if you make a type as (0=x) compiler will throw an error. In case of if(x=0) it will be an always true conditional and a very difficult error to debug.
The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. In fact, !! x is a common idiom for forcing a value to be either 0 or 1 (I personally prefer x != 0 , though).
There is no difference, code-wise.
All that's happening is that saying x=0
instead of x==0
is such a common mistake that most compilers will emit a warning (or error, in your case) when they see it. The extra set of parentheses is a common trick to shut the compiler up --- the equivalent of saying 'yes, I really meant to do this'.
Both are syntactically correct C and the compiler has to cope with it. But the compiler may, depending on the configuration, issue a warning or even error (e.g. -Werror in gcc) because one of them is so suspicious that you would never expect it to be intentional. When you use something like if (x = 0) { ... }
(assign zero to x
and run the block if zero is non-zero), you almost always actually mean if (x == 0) { ... }
(run the block if x
is zero).
Now let's get to why if ((x = 0)) { ... }
is not considered suspicious enough to warrant
the same type of warning (this particular code is still suspicious because the condition always evaluates to zero and the body is never run)...
There's an idiom used by some C developers (I'm one of them) where you put an assignment into parentheses and make use of the feature that even the assignment has a value itself and it's the assigned value.
Example:
#include <stdio.h>
int main(int argc, char **argv)
{
int c;
while ((c = getchar()) != '\n')
printf("Character: '%c' (0x%02x)\n", c, c);
return 0;
}
Test the example:
$ ./test
Hello!
Character: 'H' (0x48)
Character: 'e' (0x65)
Character: 'l' (0x6c)
Character: 'l' (0x6c)
Character: 'o' (0x6f)
Character: '!' (0x21)
The important part was the condition (c = getchar()) != '\n'
where you first assign the result of getchar()
to c
and then check it for a specific value. In this very case we are reading characters one by one from the standard input until the and of a line (technically until we read a \n
character). The main advantage of doing it this way is that it allows you to stuff the getchar()
into the test. You would otherwise have to use the comma notation, an infinite loop with a break, or put it both before the loop and at the end of the loop.
Sometimes you compare to non-zero values, like \n
, -1
and similar, but sometimes you compare to zero or, when working with pointers, to NULL
. Let's find an example for NULL
, which is pretty common with memory allocation.
char *p;
if ((p = malloc(50)) == NULL) {
...handle error...
}
Of course you could write it as:
char *p;
p = malloc(50);
if (p == NULL) {
...handle error...
}
But depending on your taste you could also use:
char *p;
if (!(p = malloc(50))) {
...handle error...
}
Or even turn it the other way round (which btw goes against my preference of always handling the error case first):
char *p;
if ((p = malloc(50))) {
...do stuff...
} else {
...handle error...
}
In the last case, the condition is (p = malloc(50))
which is exactly equivalent to p = malloc(50)
but the latter is highly suspicious because of the already mentioned common mistake of performing assignment instead of comparison in C and derived languages. Note that this is not only about suspicious compilers but also humans reading the code and looking at the potential error.
The redundant parentheses are simply a means to tell the readers and the compiler that this assignment is definitely intentional and that it's not an occurence of that common bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With