2

I'm creating a mask and setting higher bits in a short like this:

  enum FLAGS {FLAG1, FLAG2, FLAG3, FLAG4, FLAG5, FLAG6};

  public static void setFlag(short len, FLAGS flag) {
       short mask = 1 << (Short.SIZE - flag.ordinal() - 1);
       len |= mask;
  }

I printed the values:

  len: 0000001111111100
  mask : 1000000000000000
  after OR'ing with mask: 11111111111111111000001111111100

I understand that when we do bit manipulation on shorts they're upgrded to int to avoid overflow, but why are all the higher bits set then? How can I simply set any of the first 6 bits without any funny casting?

user1071840
  • 3,522
  • 9
  • 48
  • 74

4 Answers4

4

short is signed, and your mask is negative. That is preserved when it is widened to int. You can make the higher bits zero by masking the mask:

len |= (mask & 0xffff);

Now, that would be if len was an int or long, but since it is short it won't have those higher bits anyway. So really the widening is happening in some other part of your code.

kiheru
  • 6,588
  • 25
  • 31
  • @user1071840 if len is negative it can similarly be widened to a negative int **elsewhere**, not in the code you're showing. (the masking above would be quite unnecessary anyway - a short won't have those bits, and `len` can't have the value you show us). That's the technique you can use, however (but you should consider BitSet too, like Rohit Jain suggested). – kiheru Sep 30 '13 at 18:50
  • oh, now I understand.This is the situation: I have to store 6 flag values in a header which is already designed and populated and is in use. So I do not have extra space for these flags. I do have a short value which will never occupy more than 10 bits, so we've decided to use those 6 bits. Setting the highest bit in the short is unavoidable..which will of course make it negative..How should I go about? – user1071840 Sep 30 '13 at 19:36
  • @user1071840 it won't be a problem until you widen it, since as long as it is a short there won't be any higher bits. If you need to combine it with an int (or any other reason that results in a widening conversion), you can use the `len & 0xffff` technique to get an int of the 16 lower bits without the sign. – kiheru Sep 30 '13 at 19:49
0

It looks like you're OR'ing not AND'ing. '|' is or, '&' is and. Also you're OR'ing a short and an int, not a short and a short. Your print statement even says OR'ing, whereas your title says AND'ing. If you use '&=' I believe it will solve your problem.

Wond3rBoi
  • 293
  • 3
  • 11
0

When the short is converted to an int, its numeric value is preserved. If the highest bit is 1, the short is a negative number, and to preserve its value, the int would have to be negative - that is, the highest bit of the int would have to be 1 also, and so would all the bits in between.

In general, when converting a short to an int, negative numbers are left-padded with 1s and positive numbers are left-padded with 0s.

Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110
  • Thanks for the explanation..Please read the description I've posted in the previous thread (replying to @kiheru). – user1071840 Sep 30 '13 at 19:39
0

Just cast the result back to short. You're getting sign-extension in the int result, because bit 0x8000 is set in the mask, which is the sign bit.

when we do bit manipulation on shorts they're upgrded to int to avoid overflow,

No. No overflow is possible, so that can't be the reason. The reason is for consistency with other operations which can overflow, i.e. +,-,*,/.

user207421
  • 305,947
  • 44
  • 307
  • 483