! Logical operator !

Discussion in 'Mac Programming' started by cybrscot, Jan 19, 2011.

  1. cybrscot macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #1
    My book says that
    ! expr has the value 1 if the expr has the value 0

    So my problem is this. When I run the below code, it solves to 0. But 10 < 5 (i < j) is not true, so it's false, or a "0" value. Thus since there is a ! and the expr is 0, I think this should have solved as 1, not 0. I have a ! in front of a zero expr. Why am I wrong?

    The only other thing I can think of is am I supposed to read it like this..... let's say (! i < j), so do I read it as "it's not true that i is less than j", in this case, "it's not true that 10 is less than 5", which is in fact a true statement, thus equal to 1, not 0. Is this the correct way to look at it?

    i and j are int variables
    i = 10; j = 5;
    printf ("%d", !i < j );
     
  2. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    Google for "n1256.pdf" - that is the latest free draft of the C language standard. When in doubt, that document says how it is. Then look up the syntax for the "!" operator and you'll see how to read it.

    On the other hand, parentheses help you to write what you mean, help others to understand what you wrote, and most importantly they convince you and others that what you wrote is what you actually wanted to write. There is no need to learn the tiny details of operator precedence; use parentheses when in doubt.
     
  3. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #3
    The IBM website that comes up when I search logical negation says....

    Logical negation operator !
    The ! (logical negation) operator determines whether the operand evaluates to 0 (false) or nonzero (true).

    The expression yields the value 1 (true) if the operand evaluates to 0, and yields the value 0 (false) if the operand evaluates to a nonzero value.


    How do I know if the operand evaluates to zero? The problem in the book is already assigning 2 to i and 1 to j. if my book says i and j are int variables, and i = 2; and j = 1
    printf ("%d", !! i + ! j) ;

    so, since both variables i and j are already defined as non zero int, does that mean that each operand is really in fact 0, since they are both defined as non zero?

    or, since there is a ! in front of the operand, does it mean that the assigned non zero int is now changed to a 0 value?

    and what's with the double !!? My book has this in the problem, but never explained this in the chapter. Does this mean , not not?? Very confusing. :confused:

    so if i = 2, then i =2
    if ! i =2, does that mean that i isn't 2, literally not i = 2, right?
    and if ! ! i = 2, does that mean that not not i = 2, so the i's cancel each other out and in fact now i does = 2 ????

    What the heck??
     
  4. jiminaus, Jan 19, 2011
    Last edited: Jan 19, 2011

    jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    It's as important to learn the precedence of operators as it is to learn what they do.

    The precedence of an operator dictates the order in which operators are evaluated. For example, a+b*c, * as a higher precedence than +, so the order of evaluation is a+(b*c), not (a+b)*c.

    ! has a higher precedence than <. So the expression !i< j is not !(i < j), but (!i) < j.


    Now when I run this code I get 1, not 0. Here's why. When ! is applied to any integer except 0, the result is 0. So !10 is 0. This leaves 0 < 5. This is true so 1 prints out.

    (This was written before the 2 posts above).

    !! is two !'s. First !2 is 0. And then !0 is 1. So !!2 = 1.
     
  5. cybrscot, Jan 19, 2011
    Last edited by a moderator: Jan 19, 2011

    cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #5
    Damn, I can't it's a .pdf and I just tried to open it and it launches my bit torrent software instead of opening in Adobe reder. WTF? I don't know why, I don't know why the .pdf is now associated with my bit torrent app, and not reader. My system somehow changed that by itself. I don't know how to change it back to open pdf's in Adobe reader.

    Also, I don't understand your comment about parenthesis? My example does have parenthesis and my question is not at all about precedence. I don't understand why it solves to 0, when I do it on paper, I think it should solve to 1.

    Okay, thanks for explaining it, I got this one now. :)


    When I typed the above ( a few posts up, same as below in this post) book problem,

    i = 10; j = 5;
    printf ("%d", ! i < j ) ;

    I didn't use any additional paranthesis because the above is exactly how the book wrote the question. I guess what your saying is to do this....

    instead of ("%d", ! i < j ) ; you're saying to type

    ("%d", (! i) < j ) ; because it shows the precedence of the operator and helps you guys to understand what I'm typing??? Is this what you mean??
     
  6. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #6
    I think was gnasher was saying was that if there's ANY doubt in your mind about what is the order in which the operators are going to be evaluated, put in parentheses to clarify what you want. Do so also, if an expression is evaluating differently from what you expect it to do.

    So in your first example, if you wanted (!x) < y, put that in your code. If you wanted !(x < y), put that in your code. It's somewhat dangerous as a beginner to put just !x < y because the compiler's interpretation may different to yours.
     
  7. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #7
    What book are you using..? This stuff looks suspicious, and maybe it only serves to confuse you more.
     
  8. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #8
    1. If you can't read .pdf documents then you have a serious problem. If you can't even _download_ .pdf documents then you have a very serious problem. Start Safari, type n1256.pdf into the "Google" field, and when you find a link, right-click and choose "download file". And please don't use Adobe's software for reading PDFs, Preview is a lot faster and a lot safer.

    2. In software development, you don't write code that is hard to figure out, you write code that is easy to figure out. You were asking whether !i < j behaves as if you had written (! i) < j or if you had written ! (i < j). The correct answer (that is the one that I would hope for in a job interview) is that it doesn't matter; you write (! i) < j if that is what you want, and ! (i < j) if that is what you want. So you _never_ write !i < j in your code. And if you read it in someone else's code, you might figure out what it means, but you don't have any idea what the programmer who wrote it actually wanted. So in a code review, !i < j would be rejected, because nobody can know what the programmer intended.

    3. The example !i < j where i = 10 and j = 5, is chosen quite badly because no matter whether it means (! i) < j or ! (i < j), the result is 1:

    ! i is ! 10 is 0. (! i) < j is 0 < 5 is 1.
    i < j is 10 < 5 is 0. ! (i < j) is ! 0 is 1.
     
  9. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #9
    http://forums.macrumors.com/member.php?u=519139

    B
     
  10. mydogisbox macrumors member

    Joined:
    Jan 16, 2011
    #10
    Possible answer

    Getting back to what the OP was actually asking, if you have issues with a printf statement giving you a 0 instead of what you're expecting, I would check the formatting statement. This may or may not be your issue, but is important to remember either way.
     
  11. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #11
    The format specifier is not the issue here. It's the evaluation of the expression: !i < j. As have been noted already, logical not has a higer precedence than lesser than. Thus, !i is evaluated before i < j. The output is correct.
     
  12. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #12
    This book seems to have a fair number of these "gotcha!" type exercises/examples, but doesn't seem to provide explanations. cybrscot also ran into another one earlier http://forums.macrumors.com/showthread.php?t=1077572

    Code:
    (i++) + (i--)
    All good stuff, but seems to increase the likelihood of confusion in a beginner, unless it is actually being explained and just not making it through to this reader. Different readers will react differently to the same material. Some books will click with some people and others just won't.

    B
     
  13. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #13
    I guess i'd consider some of this as trivia. How would this work? If it's ridiculous and no one should ever write it, who cares? If you have source code but can't change it, I guess it might be nice, but you aren't going to be able to fix it anyway.

    I don't know that I've really seen pre- or post-increment outside of loop definitions and as independent expressions. Sticking that sort of thing in a larger arithmetic expression is just asking for trouble and confusion, and seems to serve only as a testament to the programmer's cleverness (and egotism) than toward any real goal. Saving lines of code can sometimes be noble, but not at the cost of readability.

    -Lee
     
  14. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #14
    One of the things that kept me away from C in the early days (70s-80s). It was too easy to write completely unreadable code and many folks seemed to get off on writing deliberately unreadable code just because they could. :p

    Of course Perl is the same way.

    B
     
  15. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #15
    This thread:
    http://forums.macrumors.com/showthread.php?t=1071480
    demonstrates an arguably correct use of unary * instead of binary [] to access elements in an array passed around via pointer. I am not trying to pick on the poster there, it was just one of many examples that have showed up that demonstrate what you mean. The poster there was not writing that way to intentionally obscure the meaning, they didn't know they had an option, but that's the kind of code you CAN end up with.

    Not really related to the OPs question here, but it speaks to the general idea that because something compiles and performs what you want is not the only bar one should set for their code, and expressing yourself clearly in code is at least as important as getting the desired result if this code will ever be read again (by anyone, including you).

    -Lee
     
  16. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #16
  17. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #17
    I like it fine, at least that admits it was obfuscated on purpose, just like the 7 line Perl DeCSS that was circulating for a long time. I just wouldn't recommend using that as an example in a textbook for beginners. ;)

    lee1210's point is really what I meant though. You see one way of doing something and just propagate that blindly to all your code even when something easier to read could be substituted just fine.

    B
     
  18. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #18
    I agree, it's a really good point. I think that most people who does this, ends up realizing it's value sooner or later.
     
  19. cybrscot, Jan 19, 2011
    Last edited by a moderator: Jan 19, 2011

    cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #19

    C Programming, A Modern Approach by K.N. King

    Thanks

    Thanks, I don't think my computer has a serious problem, unless you're referring to myself, which I hope you are not. I've only been using a Mac for a month. Before on my windows PC, I just clicked on a .pdf document and then it opened up in Adobe reader.

    Thanks for your help however. I'm trying to learn something new, totally new for me. All from a book with no teacher. I know for you computer guru's it's all child's play. For those of us who have never even looked at programming before it can be quite challenging. And yes it's frustrating when one tries to click on a .pdf document and it doesn't open as it normally would. I figured it has something to do with an association that got changed somehow. I took your advice and right clicked and downloaded. Remember there is so much that computers can do, some of us have not tried everything yet. Either because nobody ever showed us or we didn't spend our time clicking on everything to figure out what it does. Sometimes we're too busy working to have time to play with the computer. However I now have time that I want to use to learn something new and challenging. If only everybody would take the initiative to learn something new, instead of drinking, playing games on FB, etc. But that's enough social commentary, as this is a Mac website.
     
  20. cybrscot thread starter macrumors 6502

    cybrscot

    Joined:
    Dec 7, 2010
    Location:
    Somewhere in Southeast Asia
    #20
    Very interesting reading what everybody has written. Whether or not some of this stuff in the book is appropriate for the new beginner is neither here nor there at this point. I can tell you this, as much time as I spend trying to figure out the exercises at the end of every chapter (now CH 5) I come away with a pretty good understanding and feel more comfortable with my code. I am writing longer and longer, and more dynamic code as I get through the book. I do EVERY exercise at the end of each chapter. I want a "firm" understanding of C, so other languages after, (that are based on C) are even easier to pick up.

    So thanks for your help, it would all be in vain if I quit or gave up, I continue to push forward and will not quit. So please know that your help is appreciated and your time is not wasted.

    Thanks!:)
     
  21. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #21
    What browser are you using? In Safari it opens right in the browser window, you can then open it in preview or save it by hovering the mouse at the bottom edge of the page.
     
  22. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #22
    So you can download the document fine but cannot open it? Then right-click on the document, "Get Info", and where it says "Open with", select "Preview" and click on "Change All". Now all PDF files will be opened with Preview.
     
  23. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #23
    Because someone else might write it, and then you have to find and fix their bug.

    Or you might write it accidentally and have difficulty finding your own bug.

    I would put ! i < j in the latter category. It's the kind of thing I see and my internal alarms go off. My first thought is "WTF," shortly followed by "That can't possibly be what was intended, I'd better work this through carefully by hand." I then break out my handy chart of C operator precedence and... Step. Through. Each. Operation. Very. Carefully.

    It's unclear if the ! i < j is in the "What result does this produce? Explain." category of exercises. I'm not sure exactly what the book's author intended. I don't have the book, and the OP didn't post the complete text of the exercise. Without the complete context, we're all just guessing at the intent.

    From the two "gotcha" examples posted so far, my guess is that the book's author is trying to encourage the reader to carefully think through, and even manually work out, what each such exercise asks for. The doubled-++'s one was a little overwrought, though, since the C spec says it's undefined behavior, and I doubt any reader in the target audience would know that unless they consulted the spec, and I strongly doubt that the target audience is in the Let's-look-it-up-in-the-spec group.

    I think the ! i < j is well within the range of "What does this produce? Explain." In fact, the OP got it wrong on two counts: precedence and numeric value. The first and simplest error was operator precedence.

    The second and subtler error was failing to work through exactly what !!i produces as a numeric value (post #3). He breaks it down into individual steps (good), but doesn't actually produce the right values (bad). Instead of taking small precise steps - if i is 2, then ! 2 is 0, and then ! 0 is 1 - he goes off on a rapid-fire speculation that !!i equals 2. Wrong answer, and the reason for getting the wrong answer is failure to break it down and actually step it through. To me, that's the most important thing to learn from these exercises: breaking it down and stepping it through, and not rushing to conclusions from faulty interpretations.
     
  24. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #24
    Fully agreed, and again this is part of why C can often lead to this kind of IMHO "icky" code.

    Why do this

    Code:
    i = 10; j = 5;
    printf ("%d", !i < j );
    When you could do this?

    Code:
    i = 10; 
    j = 5;
    condition = !i < j;
    printf ("%d", condition );
    [A personal pet peeve is that I hate to see combined computation and I/O functions in code.]

    The second one may be less "efficient" in terms of source code size and maybe even memory use, but it is inherently easier to debug and also easier to port or re-use later. This is related to mydogisbox's comment earlier in the thread as you can use the debugger to separate out if condition is really 0 or if something is misbehaving in the printf. That's harder to do if you write it as a single statement.

    Intermediate variables are also a good alternative to parentheses to keep your code readable at the cost of some efficiency. e.g.

    Code:
    i = 10; 
    j = 5;
    condition = i < j;
    not_condition = !condition;
    printf ("%d", not_condition );
    removes the ambiguity of the original code.

    B
     
  25. Bill McEnaney macrumors 6502

    Joined:
    Apr 29, 2010
    #25
    What are you trying to negate: the value of i or the whole boolean expression (i < j)? You seem to negate the value of i. To negate (i < j), you could write !(i < j). To simplify that boolean expression, you can convert it to (i >= j), so you wouldn't need the "!" operator.

    Bill
     

Share This Page