Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does if((x=0)) mean in C?

Tags:

c

gcc

gcc-warning

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.

like image 856
user56220 Avatar asked Sep 21 '14 15:09

user56220


People also ask

What is the meaning of if x != 0?

if(x!=0) means "if x is not 0", so that is evaluated comparing x to 0. That might also involve an implicit conversion.

What does #if 0 mean in C?

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.

What is the difference between if 0 == x and if x == 0 )?

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.

What does != 0 mean in C?

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).


2 Answers

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'.

like image 185
David Given Avatar answered Sep 22 '22 21:09

David Given


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.

like image 23
Pavel Šimerda Avatar answered Sep 22 '22 21:09

Pavel Šimerda