views:

312

answers:

4

Hmmm. Consider this program, whose goal is to figure out the best way to get the bottom 16 bits of an integer, as a signed integer.

public class SignExtend16 {
 public static int get16Bits(int x)
 { 
  return (x & 0xffff) - ((x & 0x8000) << 1);
 }

 public static int get16Bits0(int x)
 { 
  return (int)(short)(x);
 }    

 public static void main(String[] args)
 {
  for (String s : args)
  {
   int x = Integer.parseInt(s);
   System.out.printf("%08x => %08x, %08x\n",
               x, get16Bits0(x), get16Bits(x));
  }
 }
}

I was going to use the code in get16Bits0, but I got the warning "Unnecessary cast from short to int" with Eclipse's compiler and it makes me suspicious, thinking the compiler could optimize out my "unnecessary cast". When I run it on my machine using Eclipse's compiler, I get identical results from both functions that behave the way I intended (test arguments: 1 1111 11111 33333 66666 99999 ). Does this mean I can use get16Bits0? (with suitable warnings to future code maintainers) I've always assumed that JRE and compiler behavior are both machine-independent for arithmetic, but this case is testing my faith somewhat.

A: 

yes, get16Bits0 should work, just add a suppressWarning metatag in front of the function.

CookieOfFortune
+5  A: 

Since numeric casts are implicit-friendly, I think the only reason you're getting the warning is that the compiler will always make the cast to int upon return, making your explicit cast redundant.

Yohnny
ooh! Thanks! Even better.
Jason S
+5  A: 

Well, first of all the warning is correct as you can always move "up" with arithmetic conversions. Only the other way needs a cast because you might lose data (or precision for floats).

When you reduce from int to short you have to indicate that it's intentional by using a cast. But when you convert the short value back to int there's no danger and it happens automatically.

So, all you need is

return (short) x;
Stroboskop
+4  A: 

If you wanted to avoid the cast, you could do it as:

(x << 16) >> 16

This technique also works with different numbers of bits. Say bottom 15:

(x << 17) >> 17

Change >> to >>> for unsigned version.

Tom Hawtin - tackline