Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
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 );
 
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 );

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.
 
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??
 
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.
 
Last edited:
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.

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


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.

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??
 
Last edited by a moderator:
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.
 
What book are you using..? This stuff looks suspicious, and maybe it only serves to confuse you more.
 
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.

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.
 
Possible answer

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

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.
 
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.
 
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 https://forums.macrumors.com/threads/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
 
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 https://forums.macrumors.com/threads/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

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
 
Saving lines of code can sometimes be noble, but not at the cost of readability.

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

This thread:
https://forums.macrumors.com/threads/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
 
I guess this is not to your liking then. :D

http://www.no.ioccc.org/2004/arachnid.c

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
 
What book are you using..? This stuff looks suspicious, and maybe it only serves to confuse you more.


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

Thanks

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.

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.
 
Last edited by a moderator:
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!:)
 
And yes it's frustrating when one tries to click on a .pdf document and it doesn't open as it normally would.

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

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

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

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

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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.