122

I have the following Java code:

byte value = 0xfe; // corresponds to -2 (signed) and 254 (unsigned)
int result = value & 0xff;

The result is 254 when printed, but I have no idea how this code works. If the & operator is simply bitwise, then why does it not result in a byte and instead an integer?

zb226
  • 9,586
  • 6
  • 49
  • 79
dagronlund
  • 1,612
  • 3
  • 13
  • 15

4 Answers4

191

It sets result to the (unsigned) value resulting from putting the 8 bits of value in the lowest 8 bits of result.

The reason something like this is necessary is that byte is a signed type in Java. If you just wrote:

int result = value;

then result would end up with the value ff ff ff fe instead of 00 00 00 fe. A further subtlety is that the & is defined to operate only on int values1, so what happens is:

  1. value is promoted to an int (ff ff ff fe).
  2. 0xff is an int literal (00 00 00 ff).
  3. The & is applied to yield the desired value for result.

(The point is that conversion to int happens before the & operator is applied.)

1Well, not quite. The & operator works on long values as well, if either operand is a long. But not on byte. See the Java Language Specification, sections 15.22.1 and 5.6.2.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • What does the x mean in that notation? x isn't a number or a hex number? – Callat Dec 05 '16 at 18:56
  • 4
    @KazRodgers - The `0x` (or `0X`) prefix tells Java that the integer literal that follows should be interpreted as hex (base 16). Java also supports a bare `0` prefix for octal literals and a `0b` (or `0B`) prefix for binary literals. See the [Java Language Specification](http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.1) for more info in integer literals. – Ted Hopp Dec 05 '16 at 19:15
  • The literal that follows? So for example if I had 0x3fa. The 3fa is the part being translated into a literal number and 0x is noting out "this is a hex number"? @TedHopp? – Callat Dec 05 '16 at 19:22
  • 1
    @KazRodgers - Exactly. Note that `0x` or `0b` by itself (without any digits following) is illegal syntax in Java. – Ted Hopp Dec 05 '16 at 19:26
  • Thank you for the answer. So this is basically an `Integer.valueOf(byte)` if such a function existed? Also, do you know why `int result = value;` results in `ff ff ff fe`? – Dmitry Minkovsky Feb 03 '18 at 00:53
  • 2
    @DmitryMinkovsky - The hex bit pattern `fe` in 8-bit, two's complement corresponds to the decimal value −2. To preserve the value, `Integer.valueOf(byte)` would need to produce `ff ff ff fe` (−2 in 32-bit, two's complement), not `00 00 00 fe` (decimal value 254). This transformation (from a `byte` value `fe` to an `int` value `ff ff ff fe`) is known as [sign extension](https://en.wikipedia.org/wiki/Sign_extension) and is part of the Java language specification. The purpose of `value & 0xff` is to undo the sign extension (i.e., to simulate zero extension, something Java doesn't have). – Ted Hopp Feb 03 '18 at 23:46
67

From http://www.coderanch.com/t/236675/java-programmer-SCJP/certification/xff

The hex literal 0xFF is an equal int(255). Java represents int as 32 bits. It look like this in binary:

00000000 00000000 00000000 11111111

When you do a bit wise AND with this value(255) on any number, it is going to mask(make ZEROs) all but the lowest 8 bits of the number (will be as-is).

... 01100100 00000101 & ...00000000 11111111 = 00000000 00000101

& is something like % but not really.

And why 0xff? this in ((power of 2) - 1). All ((power of 2) - 1) (e.g 7, 255...) will behave something like % operator.

Then
In binary, 0 is, all zeros, and 255 looks like this:

00000000 00000000 00000000 11111111

And -1 looks like this

11111111 11111111 11111111 11111111

When you do a bitwise AND of 0xFF and any value from 0 to 255, the result is the exact same as the value. And if any value higher than 255 still the result will be within 0-255.

However, if you do:

-1 & 0xFF

you get

00000000 00000000 00000000 11111111, which does NOT equal the original value of -1 (11111111 is 255 in decimal).


Few more bit manipulation: (Not related to the question)

X >> 1 = X/2
X << 1 = 2X

Check any particular bit is set(1) or not (0) then

 int thirdBitTobeChecked =   1 << 2   (...0000100)
 int onWhichThisHasTobeTested = 5     (.......101)

 int isBitSet = onWhichThisHasTobeTested  & thirdBitTobeChecked;
 if(isBitSet > 0) {
  //Third Bit is set to 1 
 } 

Set(1) a particular bit

 int thirdBitTobeSet =   1 << 2    (...0000100)
 int onWhichThisHasTobeSet = 2     (.......010)
 onWhichThisHasTobeSet |= thirdBitTobeSet;

ReSet(0) a particular bit

int thirdBitTobeReSet =   ~(1 << 2)  ; //(...1111011)
int onWhichThisHasTobeReSet = 6      ;//(.....000110)
onWhichThisHasTobeReSet &= thirdBitTobeReSet;

XOR

Just note that if you perform XOR operation twice, will results the same value.

byte toBeEncrypted = 0010 0110
byte salt          = 0100 1011

byte encryptedVal  =  toBeEncrypted ^ salt == 0110 1101
byte decryptedVal  =  encryptedVal  ^ salt == 0010 0110 == toBeEncrypted :)

One more logic with XOR is

if     A (XOR) B == C (salt)
then   C (XOR) B == A
       C (XOR) A == B

The above is useful to swap two variables without temp like below

a = a ^ b; b = a ^ b; a = a ^ b;

OR

a ^= b ^= a ^= b;
Community
  • 1
  • 1
Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101
5

It help to reduce lot of codes. It is occasionally used in RGB values which consist of 8bits.

where 0xff means 24(0's ) and 8(1's) like 00000000 00000000 00000000 11111111

It effectively masks the variable so it leaves only the value in the last 8 bits, and ignores all the rest of the bits

It’s seen most in cases like when trying to transform color values from a special format to standard RGB values (which is 8 bits long).

Great Explanation See here

Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
0

In 32 bit format system the hexadecimal value 0xff represents 00000000000000000000000011111111 that is 255(15*16^1+15*16^0) in decimal. and the bitwise & operator masks the same 8 right most bits as in first operand.

Eka
  • 14,170
  • 38
  • 128
  • 212