Originally posted by Barry Gaunt: Corey, you now have a class named after you! I'm going to pass this one around the office.
I have a what?!?
Okay, I've given you a day to do this: So now I suppose I'll explain the answer, in case you haven't figured it out already.
We start with "byte b = -13;" Well, what does 13 look like in binary? To determine 2's complement, start with the binary of +13, flip the bits, and add 1.
00001101 (Positive 13) 11110010 (Flipped Bits) 11110011 (Add 1 - This is -13 in binary)
Now, we execute this line of code: b >>>= 1;
Here's where the trap is laid. What does a compound assignment operator do? Most people would simply rewrite that line like this:
b = b >>> 1;
That, however, isn't quite correct. The compound assignment operators include an implicit cast to the type of the left hand operand. Therefore, to rewrite b >>>= 1, you should really write this:
b = (byte)(b >>> 1);
If you'd like to read more about compound assignment operators, you can do so here.
So, what does that mean to us? Well, first of all, when we're working with bit shifts, we promote each operand. The left and right hand operands are promoted to ints (if they aren't already ints or longs). Note that the two values are promoted separately. Unlike a multiplcation operator, in which the two operands must be of the same type, one operand can be an int while another is a long and this operator will still work. Regardless, in our case, we promote b to an int and the value 1, which is a literal and is therefore already and int, is just fine.
So what does b look like as an int? Well, it looks like this:
11111111 11111111 11111111 11110011
We just add 24 1's to the byte to end up with -13 represented as an int. Now that we've performed the conversion, we can perform the operation. Let's shift b to the right 1 position using an unsigned right shift (that means we're going to push a 0 into the left side). Our value now looks like this:
01111111 11111111 11111111 11111001
Okay, no problem, right? Now, however, we need to take into account the fact that the compound assignment operator that we used includes a cast to turn that value into a byte. Anything that doesn't fit in the least-significant 8 bits is chopped off! The trap has been sprung! We're left with this:
That, of course, is a negative value. To determine what it represents, we flip the bits and add 1.
11111001 (Original Value) 00000110 (Flipped Bits) 00000111 (Added 1 - This is 7 so the original value was -7)
And we end up with b being set to the value -7, just as the program shows if you execute it.
I stumbled over this one at first, myself, before I had to take a look at what I was doing and smacked myself in the head. :roll: I guess it's a good thing I usually compile all of the code I post.
This is a good little question for any of you mock exam writers out there. I hope you all understand what is happening now.
Remember that the shift range of an int is 0 to 31 - you can't shift something 32 positions. You can determine the shift distance by evaluating the 5 or 6 least significant bits of the right-hand operand (5 bits for an int 6 for a long). In your case, you need to do this:
As you can see, trying to shift by 32 is the same as shifting by 0. That's why you end up with the same value that you started with.
The same thing can also be done by this. If your right argument or shift distance is "shift" and your left argument or variable to be shifted is "x" then first u check the promoted type of x. Is promoted type of x a int or a long. (byte, short, int have promoted types int. long is long) If the type is an int do this shift=shift%32 else if the type is a long do this shift=shift%64
If the resulting shift is negative (<0) then do this shift=shift+32.
Useful trick to get at the actual shift distance. [ June 17, 2004: Message edited by: Swamy Nathan ]
This works, of course, because performing a "% 32" returns the 5 least significant bits of the value, which is exactly the same as the operation I showed above using bit operations. Ahhh yes, the wonderful world of powers of 2.