Thread: what does !c mean?

  1. #1
    Registered User
    Join Date
    Aug 2010
    Posts
    230

    what does !c mean?

    it is about homework but i do not understand what !c is... please help...thanks....
    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. #2
    Registered User
    Join Date
    Oct 2010
    Posts
    21
    it means if c=0 then s=s+p else p=p*a

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    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. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    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. #5
    Registered User
    Join Date
    Oct 2010
    Posts
    21
    yup!!! ur ryt... i shud have been precise... sorry

  6. #6
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    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".
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    1,262
    Quote Originally Posted by anduril462 View Post
    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. #8
    Registered User
    Join Date
    Jul 2010
    Location
    Oklahoma
    Posts
    107
    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 )
    Instead of:

    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
    Last edited by new_ink2001; 11-22-2010 at 07:57 AM. Reason: closing/semantics
    Kept the text books....
    Went interdisciplinary after college....
    Still looking for a real job since 2005....

    During the interim, I may be reached at ELance, vWorker, FreeLancer, oDesk and WyzAnt.

  9. #9
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    @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.
    Last edited by claudiu; 11-22-2010 at 08:15 AM.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  10. #10
    Registered User
    Join Date
    Nov 2010
    Posts
    7
    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. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by b1nd3r View Post
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Quote Originally Posted by Elysia View Post
    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.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    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. #15
    Registered User
    Join Date
    Jul 2010
    Location
    Oklahoma
    Posts
    107
    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
    Last edited by new_ink2001; 11-24-2010 at 02:58 AM. Reason: intra-board citation & code semantics
    Kept the text books....
    Went interdisciplinary after college....
    Still looking for a real job since 2005....

    During the interim, I may be reached at ELance, vWorker, FreeLancer, oDesk and WyzAnt.

Popular pages Recent additions subscribe to a feed