# Thread: what does !c mean?

1. ## what does !c mean?

Code:
```#include <stdio.h>

int main(){
int n=10;
float a=2, p=3, s=5;
int c=0;

while ( n>0 ){
c = n%2;
if (!c){ // what does !c mean?
s = s + p;
}else{
p = p * a;
}
n = n - 1;
}
printf("n: %d, a: %f, p: %f, s: %f,  c: %d\n", n, a, p, s, c);
return 0;
}```

2. it means if c=0 then s=s+p else p=p*a

3. Actually, it means if (c == 0). To be precise, if you replaced if (!c) with if (c = 0), you would modify the value of c, which is most certainly what you don't want. The conditional statement is evaluated, setting c to 0, the it checks the value of c as a logical expression in itself. The following two pieces of code are equivalent:
Code:
```if (c = 0) {    // this assigns c a value of zero as well as checking it's logical value
// do nothing
}
else {
printf("foo");
}```
Code:
```c = 0;
if (0 == c) {     // you could also do if (!c)
printf("foo");
}```
This is why many people do comparisons with the constant part of the expression (if there is one) on the left hand side, like so: if (0 == c). That way, the compiler will refuse to assign a variable to a constant, and you will catch such errors.

4. I didn't say it explicitly, but !c and c = 0 are most definitely not equivalent. As a matter of fact, they behave differently, depending on the value of c. As a test, I wrote this small program. Try running it as is, with c = 0, and notice that the two if clauses are not equivalent. Then, try changing c to some non-zero value (perhaps 5), recompile and re-run. Notice now that they match logically, but after the second one, c has been changed. Thus, !c and c = 0 are not equivalent.

Code:
```#include <stdio.h>
#include <string.h>

int main(void)
{
int     c = 0;

printf("c = %d, if (!c) is ", c);
if (!c) {
printf("true\n");
}
else {
printf("false\n");
}

printf("c = %d, if (c = 0) is ", c);
if ((c = 0)) {
printf("true\n");
}
else {
printf("false\n");
}

printf("Now, c = %d\n", c);

return 0;
}```

5. yup!!! ur ryt... i shud have been precise... sorry

6. I always like to read it in my mind in terms of the not operator: (if not C)..... do something. !c is equivalent to c == 0, because 0 is the only value that negated becomes "true".

7. Originally Posted by anduril462
Actually, it means if (c == 0). To be precise, if you replaced if (!c) with if (c = 0), you would modify the value of c, which is most certainly what you don't want. The conditional statement is evaluated, setting c to 0, the it checks the value of c as a logical expression in itself. The following two pieces of code are equivalent:
Code:
```if (c = 0) {    // this assigns c a value of zero as well as checking it's logical value
// do nothing
}
else {
printf("foo");
}```
Code:
```c = 0;
if (0 == c) {     // you could also do if (!c)
printf("foo");
}```
This is why many people do comparisons with the constant part of the expression (if there is one) on the left hand side, like so: if (0 == c). That way, the compiler will refuse to assign a variable to a constant, and you will catch such errors.
It's a good point of discussion, imho. Personally, I prefer "c == 0". It just sounds better to me when you read it: "If something equals 0" makes more sense than "If 0 equals something". Also, you can more easily see what you're comparing, which is usually more interesting than to what you are comparing it.
In my opinion it's kind of a "hack-fix" to put it the other way around to avoid these errors. For anyone but beginners this type of error is extremely rare (granted, I've made them once or twice after because I mis-typed it and didn't actually read properly what I was typing). But if you do make them, any proper compiler should warn you about it. If not, you should turn your compiler warnings up or get a better compiler.
So just write "c == 0", as long as you turn on all warnings, and always - no exceptions - make sure you resolve ALL warnings!

8. After a rash of typos at the mathematics laboratory, I advised students/contemporaries to place constants on the LHS of the proposition, unless one specifically meant to perform an assignment. So why not:

Code:
`   if( 0 == c )`

Code:
`   if( c == 0 )`
That way the compiler will yelp if one were to miss the extra equal sign, of course I suppose a type cast would be necessary in order to accomplish that when comparing variables....

By the way, I like Claudiu's suggestion regarding the logic operators. The negation of a proposition seems (IMHO) to be more descriptive than "!c," and lends itself to tautologies much more effectively during the design/analysis stage.

Best Regards,

New Ink -- Henry

9. @new_ink2001
The compiler should yell anyway, granted in a different way. The way you do it would trigger an lvalue error on something like if(0 = x) whereas in the more common way if(x = 0) it would recommend something as a warning.

For example, GCC has a very stupid warning for that:
"suggest parantheses around assignment used as truth value". Oh rili?
Well, I guess at least it tells you that you have an assignment in there, so I suppose unless you are not very bright you will figure out what is going on in seconds.

The problem is, like EVOEx pointed out, most beginners don't turn their warning messages on all the way.

10. if (!c) ....
is equal to:

if (c == 0) ....

"!" is a negation, it inverts the test, like if(!c) is the inverse of if(c)
it's like to say if the variable is equal to 0 or false.

btw, this information is on k&r book, which you should be reading, right in chapter 2.

[ ]'s
regards

11. Originally Posted by b1nd3r
if (!c) ....
is equal to:

if (c == 0) ....
...
This is untrue.
! is a boolean operator.

if (c)
is interpreted by the compiler as
if (c != 0)

if (!c)
is interpreted by the compiler as
if (!(c != 0))

The ! operator will simply evaluate the expression, making it true or false, then simply invert that.

So, say c = 1, then
if (c)
if (c == true)
if (true == true)

if (!c)
if (!c == true)
if (!true == true)
if (false == true)

In the end, they will do the same thing, but they certainly aren't the same thing logically, or to the compiler, or how you want to put it.

12. Originally Posted by Elysia
This is untrue.
! is a boolean operator.

if (c)
is interpreted by the compiler as
if (c != 0)

if (!c)
is interpreted by the compiler as
if (!(c != 0))

The ! operator will simply evaluate the expression, making it true or false, then simply invert that.

So, say c = 1, then
if (c)
if (c == true)
if (true == true)

if (!c)
if (!c == true)
if (!true == true)
if (false == true)

In the end, they will do the same thing, but they certainly aren't the same thing logically, or to the compiler, or how you want to put it.
Well, define "do the same thing". To me, they "do the same thing" in the context of a boolean expression, if they have the same logic value for any given value of c.

What you point out is correct, but I fail to see how what the previous poster said is "untrue".

!(c != 0) is only true if c==0. Hence it's pretty true.

13. Because !c will first invoke operator ! on c, then compare to true, while if (c == 0) will compare c to 0, then compare to true.
So they are two different operations with the same result in the end.

14. Strictly speaking, there are no boolean operators in C since there is no boolean type (unlike C++). Any expression that is treated like a boolean is actually evaluated to produce some sort of integer value.

The ! operator works on integer expressions, and does one of two things. If the expression is non-zero, it makes it zero. If the expression is zero, it makes it non-zero. It doesn't say what kind of non-zero value, it's not some specific "true" value or 1 of 0xFFFFFFFF, not necessarily at least.

If there were a boolean operator in C, then boolean expressions could only have one of two values, true or false. That means that i and !(!i) should be equal, not just evaluate the same logically, but be equal. Since it's just integer values in C however, , i and !(!i) not necessarily the same thing. Try this:
Code:
```#include <stdio.h>

int main(void)
{
int     i = 3;

if (i) {
printf("i is TRUE\n");
}
else {
printf("i is FALSE\n");
}

if (!(!i)) {
printf("!(!i) is TRUE\n");
}
else {
printf("!(!i) is FALSE\n");
}

if (i == !(!i)) {
printf("i is equal to !(!i)\n");
}
else {
printf("WTF?!?!  i is NOT equal to !(!i)\n");
}

return 0;
}```

15. Anduril462,

There are indeed Boolean operators in the C language. In fact, they coincide with George Boole's Algebra rather well, and with the assumption that T = Z\{0} and F = {0}, they do "...only have two values." Of course, finding compiler writers that employ the pre-image of a negation when negating would be silly, eh?

The observation that C++ provides a data type honors the calculus of logic no more than using Boole's name in short hand. Why compare i to the inverse image of it's negation, rather than "¬{0}?" It does have the larger co-domain....

So rather than abuse a mapping for some laughs as so, although it may ensure job security for a little while during the maintenance phase (drum roll):

Code:
```    if (i == !(!i)) {
printf("i is equal to !(!i)\n");
}
else {
printf("WTF?!?!  i is NOT equal to !(!i)\n");
}```
Shouldn't that last conditional read something like:

Code:
```    if ( 0 != !(!i) || 0 == i ) {
printf("i is equal to !(!i)\n");      // a misnomer in the first place...
}
else {
printf("***?!?!  i is NOT equal to !(!i)\n");      // statistically, a near certainty...
}```
Besides, the point is not that ¬¬x == x, because as so many have pointed out: C is using predetermined integers (a point that Elysia and/or Laserlight addressed very well in a C++ thread) to provide images under the negation mapping, not the pre-image of x from two calls ago. Rather the point is, that the Boolean mapping C employs for the function/operator ¬ is either 0 or non-zero. Which non-zero that is is not relevant in a Boolean Logic context.

Thus, the mapping of the mapping (in this case "inversion" from within Boole's co-domain) ¬¬x has exactly the same Boolean value and x did initially, but not necessarily the same Integer (Z), Real (R), Complex (C), Rational (Q), etc....value. Nor should it. In fact, I would venture to say that one could also produce such anomalies with the conjunction/disjunction because they are mappings as well.

Just in case it helps with some of that hard working legacy code, my favorite looks like:

Code:
```#define FALSE (0==1)
#define TRUE (1==1)```
That way I don't have stray Integers floating around in the code not initializing anything.... Making that last branch look like a little odd.

Best Regards,

New Ink -- Henry