5 ms·
I'm sorry, but byte should not be a signed type. Every time I work with byte in Java I have to cast it to an int with (b & 0xFF). Utter madness.
by MattPalmer1086 4y ago
I'm sorry, but byte should not be a signed type.
Every time I work with byte in Java I have to cast it to an int with (b & 0xFF).
Utter madness.
- nayuki 4y agoFrom the article: > 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-mistake https://www.nayuki.io/page/javas-signed-byte-type-is-a-mista...
- MattPalmer1086 4y agoI should read the article, doh!
- throwbadubadu 4y agoMakes that article even more schizophrene.
- gpderetta 4y agoIt could be worse. It could be unspecified whether it is signed or not. But surely nobody would design a language like that.
- account42 4y agoWell, technically C and C++ do not have mistery-signed byte types ... because they don't have byte types but char types which may be larger than a single byte. 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.
- gpderetta 4y agoChar is the byte type in C (and thus C++), both in theory and in practice. The problem it is a very overloaded type: as a char type it is used for strings, as an integral type is used as a small integer, and, as it is blessed with special semantics (strict aliasing and sizeof(char) = 1), it is also the byte type. 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.
- account42 4y ago> Char is the byte type in C (and thus C++), both in theory 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.
- asksomeoneelse 4y agoOne of my favorites; guess the difference between the output of that code: 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.
- jrpelkonen 4y agoI don’t know if this classifies as a party trick. If one is aware of the existence of “>>>”, I would presume one would solve this problem without guesswork.
- asksomeoneelse 4y agoSo obvious it's not even fun, right ? And yet... there is a twist ! 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.
- benmmurphy 4y agoheh. if you know what is happening its guessable. 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.