Reputation: 115
I have a simple program to find my IP address and convert it to a String.
Why is the b[i]
value with (int)255
below?
public class FirstSocketProgramming {
public static void main (String arg[]){
InetAddress local = null;
try {
local = InetAddress.getLocalHost();
} catch (UnknownHostException e){
System.err.println
("Identity Crisis!");
System.exit(0);
}
byte[] b = local.getAddress();
System.out.println (b.toString());
System.out.println (b.length);
String strAddress="";
for (int i = 0; i < b.length; i++)
strAddress += ((int)255&b[i]) + ".";
System.out.println ("Local = " + strAddress);
}
}
Upvotes: 1
Views: 1137
Reputation: 839
byte
data type is based on Two's complement binary signed number representation with a value range from -128 to +127.
Positive values from 0 to 127 have it's most significant bit equal to 0 representing +
.
Here binary representation is the same as it's numeric value, for example byte 00000100 = int 4
Negative values from -128 to -1 have it's most significant bit equal to 1 representing -
However in negative range, Two's complement binary representation is NOT the same as it's numeric value, for example you would expect byte 10000100
to be equal to int 132
, but is actually -124
.
Simply casting a byte
to int
won't help.
Casting just widens 1 byte to 4 btytes, 10000100 ==> 11111111111111111111111110000100
which is equal to -124, not 132, because int
data type is also based on Two's complement. Casting byte
into int
is a step in the right direction, however you also need to get rid of all these ones in front. 255&b[i]
trick achieves that.
This is what happens in 255&b[i]
:
According to conversion rules defined in the the JLS &
bitwise operator first converts it's operands to int, which means 255&b[i]
is the same as ((int)255)&((int)b[i])
. When byte is cast to int it just gets wider:
10000100 = byte -124 ==> 11111111111111111111111110000100 = int -124
Then bitwise AND is performed.
11111111111111111111111110000100 = int -124
&
00000000000000000000000011111111 = int 255
--------------------------------
00000000000000000000000010000100 = int 132
Final result is an int 132
Upvotes: 4
Reputation: 41281
The address is written as a set of bytes, from 0 to 255. Java interprets each byte as a signed one from -128 to 127. Thus, forming a string from the bytes as signed ones would be meaningless, for example -18.14.87.-45
. This does not match the IP representation.
(int)255&b[i]
casts b[i]
to an int
while widening it, thus ignoring sign and reading it as unsigned. The (int)
is frivolous as 255
is already interpreted as something wider than 8 bits. The 0-255
value is concatenated aftwerwards. You thus get an IP like 192.168.1.200
(note that this address does not match the erronous one given before).
As a general thing doing 255&foo
(or any 2^n-1
for integer n, like 65536, or even in hex like 0xFF
) is an attempt to cast bit lengths safely.
Upvotes: 3
Reputation: 12592
The ip address is logical and with the subnet_mask to find the net_id and the host_id. In the example it's the same but very unusual. The subnet_mask can be used to carve out many net_id. Read here for an example: http://www.garykessler.net/library/subnet_masks.html.
Upvotes: 0
Reputation: 3417
It's converting the signed byte to an integer so that you get the full range of (unsigned) 8-bits, instead of showing a negative number for values over 127.
In Java, since bytes are signed, the max value for a byte is 127. So lets say the number is 128. In an unsigned byte this would be represented as 10000000b. However, with 2's complement negative numbers, this becomes -128. Doing 255 & b[i] coerces the value to an integer (32-bit) and zeroes out the high bits so you get 128 instead of -128.
Upvotes: 3