If you need an unsigned 8 bit integer then use byte. It's easy to make it unsigned in arithemtic operations (where actually sign matters) as byteValue & 0xFF
Is Java char signed or unsigned for arithmetic? - Stack Overflow
types - Unsigned short in Java - Stack Overflow
Does Java not have unsigned types?
c - How can I safely use a Java byte as an unsigned char? - Stack Overflow
Videos
If you need an unsigned 8 bit integer then use byte. It's easy to make it unsigned in arithemtic operations (where actually sign matters) as byteValue & 0xFF
In Java:
long: [-2^63 , 2^63 - 1]
int: [-2^31 , 2^31 - 1]
short: [-2^15 , 2^15 - 1]
byte: [-2^7 , 2^7 - 1]
char: [0 , 2^16 - 1]
You want an unsigned 8 bit integer means you want a value between [0, 2^8 - 1]. It is clearly to choose short/int/long/char.
Although char can be treated as an unsigned integer, I think It's a bad coding style to use char for anything but characters.
For example,
public class Test {
public static void main(String[] args) {
char a = 3;
char b = 10;
char c = (char) (a - b);
System.out.println((int) c); // Prints 65529
System.out.println((short) c); // Prints -7
short d = -7;
System.out.println((int) d); // Prints -7, Please notice the difference with char
}
}
It is better to use short/int/long with conversion.
char is unsigned. From JLS§4.2.1:
For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535
...but note that when you use any of the various mathematic operations on them (including bitwise operations and shift operations), they're widened to another type based on the type of the other operand, and that other type may well be signed:
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type
double, the other is converted todouble.Otherwise, if either operand is of type
float, the other is converted tofloat.Otherwise, if either operand is of type
long, the other is converted tolong.Otherwise, both operands are converted to type
int.
For instance, char + char is int, so:
public class Example {
public static void main(String[] args) {
char a = 1;
char b = 2;
char c = a + b; // error: incompatible types: possible lossy conversion from int to char
System.out.println(c);
}
}
Re bit-extension, if we follow the link above to widening primitive conversion:
A widening conversion of a
charto an integral type T zero-extends the representation of the char value to fill the wider format.
So char 0xFFFF becomes int 0x0000FFFF, not 0xFFFFFFFF.
From the specs
For
char, from'\u0000'to'\uffff'inclusive, that is, from 0 to 65535
Since it's 16 bits, it means they are unsigned.
You can't, really. Java doesn't have any unsigned data types, except char.
Admittedly you could use char - it's a 16-bit unsigned type - but that would be horrible in my view, as char is clearly meant to be for text: when code uses char, I expect it to be using it for UTF-16 code units representing text that's interesting to the program, not arbitrary unsigned 16-bit integers with no relationship to text.
If you really need a value with exactly 16 bits:
Solution 1: Use the available signed short and stop worrying about the sign, unless you need to do comparison (<, <=, >, >=) or division (/, %, >>) operations. See this answer for how to handle signed numbers as if they were unsigned.
Solution 2 (where solution 1 doesn't apply): Use the lower 16 bits of int and remove the higher bits with & 0xffff where necessary.
And if it does, how come it is rarely used (or at least I couldn't find any examples online)? This is coming from a C/C++ dude, so I don't know stuff in Java and so I am curious.
You can safely use a byte to represent a value between 0 and 255 if you make sure to bitwise-AND its value with 255 (or 0xFF) before using it in computations. This promotes it to an int, and ensures the promoted value is between 0 and 255.
Otherwise, integer promotion would result in an int value between -128 and 127, using sign extension. -127 as a byte (hex 0x81) would become -127 as an int (hex 0xFFFFFF81).
So you can do this:
long a = (((data[0] & 255) << 24) | ((data[1] & 255) << 16) | ((data[2] & 255) << 8) | (data[3] & 255)) & 0xffffffff;
Note that the first & 255 is unnecessary here, since a later step masks off the extra bits anyway (& 0xffffffff). But it's probably simplest to just always include it.
... can I safely use
byteas a replacement forunsigned char?
As you've discovered, not really... No.
According to Oracle Java documentation, byte is a signed integer type, and though it has 256 distinct values (due to the explicit range specification "It has a minimum value of -128 and a maximum value of 127 (inclusive)" from the documentation) there are values that an unsigned char from C can store, that a byte from Java can't (and vice-versa).
That explains the problem you've experienced. However, the extent of the problem hasn't been fully demonstrated on your 8-bit-byte implementation.
What other "gotchas" should I be aware of?
Whilst a byte in Java is required to have support for only values between (and including) -128 and 127, Cs unsigned char has maximum value (UCHAR_MAX) that depends upon the number of bits used to represent it (CHAR_BIT; at least 8). So when CHAR_BIT is greater than 8, there will be extra values beyond 255 that unsigned char can store.
In summary, in the world of Java a byte should really be called an octet (a group of eight bits) where-as in C a byte (char, signed char, unsigned char) is a group of at least (possibly more than) eight bits.
No. They are not equivalent. I don't think you'll find an equivalent type in Java, either; they're all rather fixed-width. You could safely use byte in Java as an equivalent for int8_t in C, however (except that int8_t isn't required to exist in C unless CHAR_BIT == 8).
As for pitfalls, there are some in your C code too. Assuming data[0] is an unsigned char, data[0] << 24 is undefined behaviour on any system for which INT_MAX == 32767.
-
I know that char is neither sign or unsigned because we use characters not numbers.
-
the size of a char variable is 1 byte in most compilers.
I read recently that the range of values a char variable could take is from -128 to 255. Moreover, if i want the range of values to be only positive i could use unsigned char which will give me the range from 0 to 255.
What i dont get is, why do we need unsigned when we don't store negative numbers in a char variable as a char variable takes only one char as '5' not '-5'.
I dont get why we need to use unsigned char.
A char in Java is always unsigned :
4.2.1. Integral Types and Values
The values of the integral types are integers in the following ranges:
...
For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535
Therefore, simply write :
private char[] Memory = new char[64000];
char type in Java according to the JLS is unsigned.