Every time I work with byte in Java I have to cast it to an int with (b & 0xFF).
Utter madness.
Every time I work with byte in Java I have to cast it to an int with (b & 0xFF).
Utter madness.
> Bytes are a different story however. I argue that signed bytes make programming needlessly annoying, and that only unsigned bytes should have been implemented in the first place
> https://www.nayuki.io/page/javas-signed-byte-type-is-a-mista...
If someone designed a language this way today they would be called a master troll. At least you can require CHAR_BITS == 8 in practice for everything except weird embedded systems - both POSIX and Windows do just that.
Technically C++ now does indeed have a blessed byte type (std::type). But it is not an integral type: it support bitwise operations but not artihmetic ops, so signedness doesn't come into the picture.
Not an 8-bit byte which is the definition most people think of when talking about bytes and the only one that matters once you need to interact with other systems.
> and in practice.
Yes.
> Technically C++ now does indeed have a blessed byte type (std::type). But it is not an integral type: it support bitwise operations but not artihmetic ops, so signedness doesn't come into the picture.
Its signedness does matter for casts to integral types - int(std::byte(255)) == 255 whereas int(char(255)) is implemenation-defined.
byte a1 = 0x40; byte a2 = (byte) 0x80; a1 >>= 1; a2 >>= 1; System.out.printf("0x%02X\n", a1); System.out.printf("0x%02X\n", a2);
And that code (note the operator ">>>" instead of ">>"):
byte a1 = 0x40; byte a2 = (byte) 0x80; a1 >>>= 1; a2 >>>= 1; System.out.printf("0x%02X\n", a1); System.out.printf("0x%02X\n", a2);
Congrats if you guessed right on your first try, because I certainly did not.
I don't want to spoil the ending. I encourage people to run the code on their own after they made their guess to compare.
my model which might not be correct is:
this `byte a2 = (byte) 0x80` is a cast from the integer 0x80 to a byte and when there is a cast from integer to byte it just truncates the bits. when printing out this value it interprets it as 2s compliment so its 'value' is -128. so it just takes 8 bits starting from the least significant bit. so you end up with the bits 1_000_0000. then when you do this `>>=` operator that promotes to an integer and then it does the right shift then casts back to a byte. the promotion from integer to byte is just done by sign extending the byte to 32 bits. so you get 25 1's followed by 7 0's. the shift is a signed shift so you get 26 1's followed by 6 0's. then the cast back to byte leaves you with 11_000_000 which is why you get the 'weird' result of 0xC0 which is larger than 0x80. and the unsigned shift works in a similar way except the intermediate result is 0 followed by 25 1's followed by 6 0s. but this values in the high bits have no effect after the truncation which is why you get the same result.
you need to do `a2 & 0xFF` to clear out the sign bits outside the byte range before applying the shift in order to do the unsigned byte to unsigned int (or signed int?) promotion correctly. but using unsigned types in java is super dangerous.