Equivalent in Java - java

Taking me hours already to figure this out by googling and I think need help here. I have a snippet that is causing it not to work like its equivalent in objective c so would need some experts' help.
What are the equivalent of the objective c snippets below in java?
unsigned char mByte[CC_SHA1_DIGEST_LENGTH];
uint64_t tBytes = 0xFFFFFFFF;

Well there is no absolute equivalent, if all languages were the same why would we need more than one?
The closest thing is probably:
final int CC_SHA1_DIGEST_LENGTH = 1024; //some length
char[] mByte = new char[CC_SHAR1_DIGEST_LENGTH];
//there is no unsigned keyword in java
//The long data type is a 64-bit two's complement integer
long tBytes = Long.MAX_VALUE;
long tBytes=0xFFFFFFFF; would also work, but this is a negative number (because it is treated as an integer, not a long). If you want it to be long you need to add L (0xFFFFFFFFL) at the end. Be careful!
More info on the primitive datatypes can be found here.

unsigned char mByte[CC_SHA1_DIGEST_LENGTH];
equivalent in java will be
final int CC_SHA1_DIGEST_LENGTH=1024;
byte mByte[CC_SHA1_DIGEST_LENGTH];
though mByte is unsigned so when you work with mByte array you have to convert byte value to unsigned using 0xFF.
for example,
mByte[0]=(0x88 & 0xFF);
uint64_t tBytes = 0xFFFFFFFF;
equivalent in java will be
long tBytes = 0xFFFFFFFF;

Well the rule of thumb would be to match type lenght's in bits.
In C unsigned char is 8 bit wide, so Java equivalent would be byte.
In C uint64_t is 64 bit wide, so Java equivalent would be long.
So therefore Java equivalent would be:
//SHA1 lenght would be 20 bytes
public static final int CC_SHA1_DIGEST_LENGTH = 20;
byte mBytes[] = new byte[CC_SHA1_DIGEST_LENGTH];
long tBytes = 0xFFFFFFFF;
#user3200809
mByte[0]=(0x88 & 0xFF); - this operation is pointless unless you have value larger than 8 bits.
See the same operation in binary:
1000 1000
&
1111 1111
=
1000 1000
When assigning to mByte[i] you would have to type cast to byte anyway so all excessive bits will be chopped.
When we look at memory representation of those types there is no difference between signed and unsigned types.
I'm guessing from authors post that he works with SHA1 algorithm which is bunch of binary operations (xor's, and's, shift's).
So for binary operations there is no difference that type is signed or unsigned:
byte b = (byte) 0x80; //-128 in signed decimal
b ^= (byte) 0x01;
System.out.printf("0x%x", b); // prints 0x81 which is -127 in signed decimal
BUT you could run into problems if you're doing e.g. division.

Related

Fixing "incompatible types: possible lossy conversion from int to byte" in Java

I have question regarding my code here:
public class Main
{
public static void main(String[] args) {
System.out.println("Hello World\n");
int x = 36;
byte b1 = ((byte) x) & ((byte) 0xff); // it seems it is the part after &, but I have 0xff cast to byte by using (byte)0xff, so not sure where exactly the error is coming from.
System.out.println(b1);
}
}
I am not sure exactly which part is causing the error of:
incompatible types: possible lossy conversion from int to byte
This is the error message output from the program:
You appear to be confused.
There is no point in your code. taking any number, calculating that & 0xFF, and then storing it in a byte, is always a noop - it does nothing.
You additionally get an error because & inherently always produces at least an int (it'll upcast anything smaller to match), so you're trying to assign an int to a byte.
What are you trying to accomplish?
"I want to have my byte be unsigned"!
No can do. Java doesn't have unsigned bytes. A java byte is signed. Period. It can hold a value between -128 and +127. For calculation purposes, -128 and 255 are identical (they are both the bit sequence 1111 1111 - in hex, 0xFF, and they act identically under all relevant arithmetic, though it does get tricky when converting them to another numeric type int).
"I just want to store 255"!
Then use int. This is where most & 0xFF you'll ever see in java code comes from: When you have a byte value which java inherently treats as signed, but you wish to treat it as unsigned and, therefore (given that in java bytes can't do that), you want to upcast it to an int, containing the unsigned representation. This is how to do that:
int x = y & 0xFF;
Where y is any byte.
You presumably saw this somewhere and are now trying to apply it, but assigning the result of y & 0xFF to a byte doesn't mean anything. You'd assign it to an int variable, or just use it as expression in a further calculation (y & 0xFF is an int - make sure you add the appropriate parentheses, & has perhaps unexpected precedence).
int x = 36;
byte b1 = ((byte) x) & ((byte) 0xff);
Every imaginable way of this actually working would mean that b1 is... still 36.
To compute x & y where the two operands are bytes, they must first be promoted to int values. There is no & between bytes. The result is therefore of type int
That is, what you wrote is effectively evaluated as if you'd written it as the following, making explicit what the language gives you implicitly:
byte b1 = ((int) (byte) x) & ((int) (byte) 0xff);
Just do the arithmetic and then cast the result to byte.
byte b1 = (byte)(x & 0xff);
Link to Java Language Specification
Edited to add, thanks to #rzwitserloot, that masking a byte value with 0xff is however pointless. If you need the assignment from an integer to a byte, just write the cast:
byte b1 = (byte)x;

Converting int to byte [duplicate]

This question already has answers here:
Odd behavior when Java converts int to byte?
(12 answers)
Closed 9 years ago.
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
I was looking at this code and was confused about how they values were stored. The first int is stored as 32 bits (4 bytes). b converts to binary and stores its signed value (8 bits). Does i2 store it as an 8 bit unsigned representation or does it convert it back to 32 bits?
Java does not have unsigned primitive types. All byte variables are signed 8-bit values.
Whether or not the most significant bit is interpreted as a sign bit, when you do bit-wise operations all the bits that are present are used by the operator. To make this concrete, the following are equivalent:
i2 = b & 0xFF;
i2 = b & ((byte) -1);
i2 is declares as an int, so it should be a full 32-bit value. It will contain the binary AND of b, which in this case is the lower 8 bits and 0xFF.
Things aren't "stored as" an unsigned or signed representation. This is a nitpicky distinction, but it seems to be where you're getting confused. The only difference is how the bits are interpreted. What's happening here is the following:
i stores the value 11101010 (plus some number of higher order bytes). Under Java's convention for integer storage format, this represents the value 234.
b stores the value 11101010, since ints are converted to bytes by simply truncating them. Under Java's convention for numerical byte storage format, this represents the value -22.
i2 stores the value 11101010 (plus some number of higher order bytes), because a bitwise operation was applied to b so its bits were directly copied. (Had you written int i2 = b or int i2 = b + 0, the byte would have been converted to its numerical value -22, and then stored as the int representation of -22.

consolidating bytes in java

As part of a program I'm writing I need to consolidate two bytes into a long from an array of bytes.
So assuming this:
byte a[] = new byte[2]
a[0] = 0b1000111
a[1] = 0b1111000
how can I consolidate them such that
long b = 0b10001111111000
EDIT: The program will attempt to consolidate anywhere between 2 bytes and 100, just for reference.
java.nio can do that:
ByteBuffer.wrap(a).getShort()
BigInteger can do this: http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html
BigInteger buffer = new BigInteger(yourByteArray);
long result = buffer.longValue();
Note that if your byte array has a value larger than a long (eg, you mentioned that you might go up to 100 bytes), toLong() will only return the value of the lower value bytes. BigInteger, however, will handle any arbitrary number of bytes.
In order to combine those two bytes you will only need 16 bits. A short will suffice:
short result = (short)(((a[0] & 0xff) << 8) | (a[1] & 0xff))
If for some reason, you need the long data type, you need only replace the cast with a long.

Is there a way to represent int value in byte over 127 without doing bitwise operations?

I am really short on time for doing the learning of bitwise operations.
I want to convert large integer(>127) values without doing '<<' or anything similar.
I need byte representation of integer values used to identify sequence numbers of packets in header sent across UDP. If there is no solution I will introduce two bytes..
Something like: 1, 1 ; 1,2 ; 1,3 ; packet lost ; 1,4 ; packet lost; 2,1 ,2,2
and then reset it upon reaching 127; 127
I can introduce third, but this is rather ugly.
It would be really useful to have black box that is part of java api doing all that byte conversion for me. Is there?
Thanks,
To pack an unsigned 8-bit value into a byte:
static byte toByte(int i) {
if ((i < 0) || (i > 255))
throw new IllegalArgumentException(String.valueOf(i));
return (byte) i;
}
To convert back:
static int toInt(byte b) {
return (b < 0) ? (b + 256) : b;
}
After reading your comments on other answers, it sounds like you might want something like this:
byte[] b = BigInteger.valueOf(counter).toByteArray();
and
long counter = new BigInteger(b).longValue();
Since the length of the array would vary as the counter grows, you'd need some way to indicate its length or delimit it. But this technique will convert any integer value to an array of bytes.
Is the problem that you want unsigned bytes, as in, numbers between 128 and 255 inclusive?
That's...tricky. The Java language won't let you directly treat bytes as unsigned...but with library support it gets a little easier. Guava provides an UnsignedBytes utility class for some of these needs. Addition, multiplication, and subtraction are all exactly the same on signed and unsigned bytes.
EDIT: Judging from your additional comments, you might be interested in Ints.toByteArray(int) and the like, which work on types between byte and BigInteger.
According to my understanding, you want to separate an int into 4 bytes. If so, then just copy paste this code:
int i = /* your int */
int[] b = { (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff };
Indices 0-3 are each of the 4 bytes in the int.

unsigned long in java, using BigInteger for arithmetics, but BigInteger.toByteArray returns 14 bytes instead of 8

I have the following c code which id like to port to Java
unsigned long long* data=(unsigned long long*)pBuffer; // file data
unsigned long long crypt = 0x0000;
unsigned long long next_crypt;
unsigned int len = size >> 3;
for(unsigned int i=0; i<len;i++) {
next_crypt = crypt+data[i]-0xCAFEBABE;
data[i] = ((data[i]<<0x1d)|(data[i]>>0x23))+0xCAFEBABE;
data[i] = (data[i]<<0x0e)|(data[i]>>0x32);
data[i] = data[i] - crypt;
crypt = next_crypt;
}
I tried to port this to java using long, however this would result in negative values. Therefor i switched to biginteger since i have to do arithmetics (bit shifting etc).
I got the desired 64bit unsigned long value using BigInteger, however when i wanted to convert it to byte (BigInteger.toByteArray) it was 14 bytes long and no longer 8 bytes - so i cannot modify my array/file anymore. I tried using toLongValue() but the data was incorrect.
Thanks
Your C code is relying on bits being shifted off the high-order end of the unsigned long long. (These are rotated around to the other end by the other shift.) BigInteger is arbitrary precision and hence has no end, so left-shifted bits are never shifted off.
You could construct a 64-bit BigInteger bitwise AND mask and AND it after the left shifts. This is an intuitive solution.
You could also just simply ignore the high-order bytes.
byte[] bar = foo.toByteArray();
if (bar.length > 8) {
bar = System.arrayCopy(bar, bar.length - 8, new byte[8], 0, 8);
}
If len is large, then this simple solution would be wasteful of memory.
In any case there is a saner and higher-performing solution. Java's signed integer types are all guaranteed to have two's complement semantics. The bit semantics for arithmetic with two's complement integers and unsigned integers are identical--the difference is only in the interpretation of the value! So just use the original C code (substituting in Java's long) and at the end, interpret them your way.
byte[] longToByteArray(long x) {
byte[] array = new byte[8];
for (int i = 7; i >= 0; i--) {
array[i] = (byte)x;
x >>>= 8;
}
}
By the way, be sure you replace the >> operator in the C code with Java's >>> operator.
The nice thing about Java is that it's guaranteed to be twos-complement, so provided you use >>> instead of >> and avoid % and / and inequalities, arithmetic is effectively unsigned anyway.

Categories