Byte-fibbel med Java

Nån mer än jag som svurit över att unsigned inte finns i Java? Det är väl inte så farligt tyckte jag först. Man vänjer sig väl. Det sade jag 1998 men jag har tydligen inte vant mig än.

I en byte-array har jag på index 2 och 3 två bytes som representerar värdet av en 16-bits hårdvaruräknare. 0 till 65535 alltså. Dessa två bytes skall jag alltså packa ihop till en enda integer. Svårare uppgifter har jag klarat av [tiddelipom].

Men ok, jag skriver väl en liten test – bajtarna i Java kan bitas.

Den första byten (MSB) får vara 0xAA och den andra sätter jag till 0xBB. Resultatet skall alltså bli 0xAABB, hur svårt kan det vara? (varför håller jag på att provköra såna här enkla tramsuppgifter egentligen?)

Typ så här minns jag funkade utmärkt i C:

byte msb_b, lsb_b;
...
int counterValue = ( msb_b << 8 ) | lsb_b;
System.out.printf("counterValue=0x%04x\n", counterValue);
...
counterValue=0xffffffbb

Äsch. Men jag kände på mig att sign extension skulle bita mig nånstans. Jag struntar i bit-operatorerna och gör det enkelt och tydligt istället:

int counterValue = msb_b * 256 + lsb_b;
…
counterValue=0xffffa9bb

Hm. Det blev ju inte alls bra det heller (undrar om någon ser vad jag håller på med).

Jag tror jag konverterar bytarna till int så fort det går för att undvika problem:

int tmp_msb_i = msb_b;
int tmp_lsb_i = lsb_b;
int counterValue= ( tmp_msb_i << 8 ) | tmp_lsb_i;
…
counterValue=0xffffffbb

Ojdå. Hittils inte ett resultat rätt och dessutom alla olika. Tur att enhetstest finns.

Dags att ta sig an detta seriöst:

public static int convert(byte b) { return (int) b & 0xff; }

int counterValue = ( convert(msb_b) << 8 ) | convert(lsb_b);
…
counterValue=0xaabb

Ja!!! Rätt!!! Där satt det!!! Så skall en slipsten dras!

Oops. Det var väl ingen som hörde det där. Jag bör nog inte sitta här och vara stolt över att ha lyckats packa ihop en int från två bytes.

Men jag kan ju inte anropa en metod för en sån tramsuppgift. Jag testar hur det ser ut inline:

int counterValue = ( ((int) msb_b & 0xff) << 8 ) | ( (int) lsb_b & 0xff );

Mmmm.... nästan oläsligt.

Om jag skulle gå tillbaka till det ursprungliga och skifta och ORa bytes men tvinga in resultatet i en short istället?

short counterValue = (short) (( msb_b << 8 ) | lsb_b);
System.out.printf("counterValue=%04x\n", counterValue);

Det printar också rätt resultat.

Men vänta nu, resultatet är i en short som är en 16-bit signed integer. Måste konverteras till int innan jag kan använda den:

int counterValueInt = counterValue;
System.out.printf("counterValueInt=%04x\n", counterValueInt);
…
counterValue=0xffffffbb

17 också!!! Tillbaka till gå igen utan att inkassera 4000. Stunder som den här längtar jag tillbaka till gamla hederliga C.

IT Consultant at CAG Edge. Cloud and Continuous Delivery specialist, software developer and architect, Node.js, Java.

Publicerad i Java

Kategorier

WP to LinkedIn Auto Publish Powered By : XYZScripts.com