Hinsichtlich der simulerten Schreib/Leseoperationen auf ein byte[] in Java habe ich festgestellt, dass man noch einigen zusätzlichen Aufwand betreiben muss, um korrekte unsigned 16/32-Bit-Werte aus dem Speicher zu lesen oder dorthin zu schreiben. Zuerst muss man beachten, dass Java nur signed 16/32-Bit-Werte bereitstellt. Auch wenn das höchte Bit weiterhin verfügbar ist, muss, um korrekt rechnen zu können, jeweils der nächstgrößere Datentyp verwendet werden. Bei den Konvertierungen der 8-Bit-Werte aus dem Array muss zuerst in den Zieltyp gecastet und mit 0xFF maskiert werden, bevor die Werte geshiftet und zum Resultat kombiniert werden. In der umgekehrten Richtung reicht allerdings ein Shift und ein Cast, wahlweise mit Maskierung vor oder nach dem Shift.
Bei den auftretenden Casts habe ich folgendes Verhalten beobachten können:
(byte) 0x7F -> (short) 0x007F // wird mit Nullen aufgefüllt
(byte) 0x80 -> (short) 0xFF80 // wird mit Einsen aufgefüllt
(short) 0x007F -> (byte) 0x7F
(short) 0x0080 -> (byte) 0x80 // Vorzeichenwechsel
(short) 0xFF80 -> (byte) 0x80
(short) 0xFF7F -> (byte) 0x7F // Vorzeichenwechsel
Während das Verhalten der ersten beiden Erwartungsgemäß ist, kam mir das Verhalten des 4. und 6. Casts etwas merkwürdig vor.
Bei einem Cast in einen größeren Datentyp werden die oberen Bytes mit dem höchsten Bit (=Vorzeichenbit) des Ausgangswerts aufgefüllt. Bei einem Cast in einen kleineren Datentyp werden die oberen Bytes einfach abgeschnitten, das höchste Bit des Resultats bleibt unverändert. Hier findet also bei jeder negativen Zahl ein Overflow und möglicherweise auch ein Vorzeichenwechsel statt.
Auf den 2. Blick ist dieses Verhalten allerdings nachvollziehbar, da korrekt gecastet wird, falls der (negative) Ausgangswert in den Datentyp des Resultats passt. In diesem Fall ist das höchste Bit des Resultats im Zweierkomplement bereits korrekt gesetzt