What is the result of attempting to compile and run the program? a. Prints: 0,0 b. Prints: -1,4 c. Prints: 0x1f,8 d. Prints: 31,16 e. Run-time error f. Compile-time error g. None of the above ANS: g Explanation: Prints 31,0. The expression, (-1 & 0x1f), is equal to (0xffffffff & 0x1f), and both are equal to the hex value, 0x1f, or decimal 31. The expression (8 << -1) is equivalent to (8 << 0xffffffff). If the left hand operand of a shift expression is of type int, then the right hand operand is implicitly masked with the value 0x1f. The expression (8 << 0xffffffff) can therefore be simplified to (8 << 0x1f). The decimal equivalent is (8 << 31). When 8 is shifted 31 bits to the left, the result is zero since the only non-zero bit is lost as it is shifted beyond the most significant bit of the int data type. I'm clear on the first part of the explanation. I have the following 2 doubts: 1. If the left hand operand of a shift expression is of type int, then the right hand operand is implicitly masked with the value 0x1f. The expression (8 << 0xffffffff) can therefore be simplified to (8 << 0x1f). The decimal equivalent is (8 << 31).

Could somebody explain what is meant by 'masking'? 2. When 8 is shifted 31 bits to the left, the result is zero since the only non-zero bit is lost as it is shifted beyond the most significant bit of the int data type.

------ Here's another simple problem: int i = 1 << 33; // would be equivalent to 1 << 1 which is equal to 2. System.out.println (i); // would print 2 I always thought that when left shift operator is applied, the values just 'wrap' around. Here's how I would solve it if I applied Dan's explanation in point 2 above: The non-zero bit should be lost after shifting it by 31 bits and on subsequent shifts, I should get 0 as the result. ------ Am I missing something here (obviously I am)? Also, can you guys recommend any good online tutorials which can help clear this concept? My certification exam guide (Khalid Mughal for SCJP 1.2) doesn't cover this topic in depth. Thanks Harwinder [ October 24, 2003: Message edited by: Harwinder Bhatia ]

Okay, let's consider what "masking" is, first of all. To think of this literally, consider what a mask (such as a Halloween mask) is. It's something that blocks most of the visible area and only reveals a small portion (kind like cutting a hole in a piece of paper and covering something with it). It's with that same notion that we apply "bit masks." A bit mask is something that hides everything except a small portion that we care about. For example, let's say we have the number 43 and we want to know what the least significant bit is (the least significant bit is the digit representing 2^0). In order to do that, we apply a bit mask. Let's see how this is done:

As you can see, we applied the & operator to our original value and our bit mask. What does that do for us? Well, it masks the rest of the data (everything except the least significant bit) and leaves us with what we want to see. Bit masks can be applied a number of ways to do all sorts of useful things. This was just one simple example, but I hope it helps you understand what is meant by masking. Ok, for the second part of your question, shifting bits DOES NOT WRAP. If you shift a bit off the end, it's gone forever. Imagine that the bit just fell into a digital black hole. So, let's say you've got the number 127, which, in binary, is 01000000. Now, if we shift that left 1 space, we have 10000000. If we shift left once more, we have 00000000 (Gasp! The 1 fell off and is gone forever). No matter how many times we shift it now, we're never going to come up with something besides 0. I hope that helps.

Hi Corey Thanks for your response. 1. Now I kind of understand the concept of masking. Now could somebody please explain me why the mask of 0x1f is applied to the RH operand, if the left hand operand of a shift expression is of type int? I think this is deduced from something ... I just want to understand what that is? 2.

shifting bits DOES NOT WRAP

If this is the case, how does 1 << 33 equal to 2? According to your explanation, it should be 0, because in the following expression: 0000 0000 0000 0000 0000 0000 0000 0001 << 33 1 should just fall off at the 32nd shift, then how come the result is 2? I'm really confused here. 3. My last question is still there: can somebody please recommend any good resources (online tutorials or books other than Khalid Mughal that I have), which could explain this concept in depth. Thanks Harwinder

1. Now I kind of understand the concept of masking. Now could somebody please explain me why the mask of 0x1f is applied to the RH operand, if the left hand operand of a shift expression is of type int? I think this is deduced from something ... I just want to understand what that is?

If the left hand operand is of type int, then shifting more than 31 bits to the left always produces zero. Therefore, there is no point in allowing larger shift distances.

Originally posted by Harwinder Bhatia:

2. If this is the case, how does 1 << 33 equal to 2? According to your explanation, it should be 0, because in the following expression: 0000 0000 0000 0000 0000 0000 0000 0001 << 33 1 should just fall off at the 32nd shift, then how come the result is 2? I'm really confused here.

33 & 0x1f = 1. 1 << 1 = 2

Dan Chisholm<br />SCJP 1.4<br /> <br /><a href="http://www.danchisholm.net/" target="_blank" rel="nofollow">Try my mock exam.</a>

Dan Chisholm
Ranch Hand

Joined: Jul 02, 2002
Posts: 1865

posted

0

Harwinder, I would like to improve the explanation that appears on the exam. Is this new version an improvement over the old?

Prints 31,0. The expression (-1 & 0x1f) is equal to (0xffffffff & 0x1f), and both are equal to the hex value 0x1f or decimal 31. The expression (8 << -1) is equivalent to (8 << 0xffffffff). If the left hand operand of a shift expression is of type int, then the right hand operand is implicitly masked with the value 0x1f. In other words, the expression (8 << -1) is equivalent to (8 << (-1 & 0x1f)). By replacing -1 with the hexadecimal representation we have (8 << (0xffffffff & 0x1f)). By evaluating the right hand operand we have (8 << 31). When 8 is shifted 31 bits to the left, the result is zero since the only non-zero bit is lost as it is shifted beyond the most significant bit of the int data type.

Harwinder Bhatia
Ranch Hand

Joined: Oct 17, 2003
Posts: 150

posted

0

Hi Dan Thanks for the response. First let me tell you that your mock exams are absolutely fabulous. They have really helped me a lot in my preparation for SCJP. In particular, they have helped me identify my weak areas. I find them so intriguing because you have so many variations on the same question .. it's like you cover all the different permutations & combinations on a particular topic and there's nothing else left. Once I go through an exam thoroughly, I feel so much more confident on the topic. I am really thankful to you for providing us with such a great resource free of cost. If I were to make a conservative estimate, I would say, I would score 20% more in my exam with the help of your questions as compared to without them (Btw, I'm yet to touch on Marcus' exam and hence, not commenting on them). This question which I posted is just one such area I need to consolidate on. I don't find any problem with your explanation (most of your explanations are very explicit and to the point) if I assume that when the left operand is an integer then right operand is masked with 0x1f (thanks to Corey for giving such a wonderful explanation of masking). Now my only doubt is where does the number "0x1f" come from? Why mask with "0x1f", why not anything else? I would appreciate if you could explain this to me. Thanks again. Harwinder

subject: Dan's Question: Operators and Assignments