In the following snippet consider replacing line 8 with commented equivalent
1. private static String ipToText(byte[] ip) {
2. StringBuffer result = new StringBuffer();
3.
4. for (int i = 0; i < ip.length; i++) {
5. if (i > 0)
6. result.append(".");
7.
8. result.append(ip[i]); // compare with result.append(0xff & ip[i]);
9. }
10.
11. return result.toString();
12. }
.equals()
test confirms that adding 0xff
does not change anything. Is there a reason for this mask to be applied?
byte
in Java is a number between −128 and 127 (signed, like every integer in Java (except for char
if you want to count it)). By anding with 0xff
you're forcing it to be a positive int
between 0 and 255.
It works because Java will perform a widening conversion to int
, using sign extension, so instead of a negative byte
you will have a negative int
. Masking with 0xff
will leave only the lower 8 bits, thus making the number positive again (and what you initially intended).
You probably didn't notice the difference because you tested with a byte[]
with only values smaller than 128.
Small example:
public class A {
public static void main(String[] args) {
int[] ip = new int[] {192, 168, 101, 23};
byte[] ipb = new byte[4];
for (int i =0; i < 4; i++) {
ipb[i] = (byte)ip[i];
}
for (int i =0; i < 4; i++) {
System.out.println("Byte: " + ipb[i] + ", And: " + (0xff & ipb[i]));
}
}
}
This prints
Byte: -64, And: 192
Byte: -88, And: 168
Byte: 101, And: 101
Byte: 23, And: 23
showing the difference between what's in the byte
, what went into the byte when it still was an int
and what the result of the &
operation is.
As you're already working with an array of bytes here, and you're doing a bitwise operation, you can ignore how Java treats all bytes as signed. After all, you're working on the bit level now, and there is no such thing as "signed" or "unsigned" values on the level of bits.
Masking an 8-bit value (a byte) with all 1's is just a waste of cycles, as nothing will ever be masked off. A bitewise AND will return a bit true if both bits being compared are true, thus if the mask contains all 1's, then you're guaranteed that all bits of the masked value will remain unchanged after the AND operation.
Consider the following examples:
Mask off the upper nibble: 0110 1010 AND 0000 1111 (0x0F) = 0000 1010
Mask off the lower nibble: 0110 1010 AND 1111 0000 (0xF0) = 0110 0000
Mask off... Eh, nothing: 0110 1010 AND 1111 1111 (0xFF) = 0110 1010
Of course, if you were working with a full blown int here, you'd get the result at the others have said: You'd "force" the int to be the equivalent of an unsigned byte.
In this example, I don't see how it would make any difference. You are anding the 0xff with a byte. A byte by definition has 8 bits, and the add masks off the last 8 bits. So you're taking the last 8 of 8, that's not going to do anything.
Anding with 0xff would make sense if the thing you were anding with it was bigger than a byte, a short or an int or whatever.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With