Tyyppimuunnokset (cast) / bittikäs.

Tyyppimuunnokset (cast) / bittikäsittely

Tyyppimuunnokset:

delphissä voi tehdä esim. näin:

type

LongRec = packed record

B0, B1, B2, B3 : Byte;

end;


procedure Test1;
var

L : Longint; // 32 bits

T0, T1, T2, T3 : Byte; // 4 tavua, 8 bit/tavu

begin

L := $cafeBabe; // ylin tavu (MSB) on ca (hex)

// alin tavu (LSB) = be (hex)

T0 := LongRec(L).B0;

T1 := LongRec(L).B1;

T2 := LongRec(L).B2;

T3 := LongRec(L).B3;

// nyt myös T0 = be (hex) ja T3 = ca (hex)

end;

Miten vastaavan voisi tehdä javalla ?

Siis esim:

class TestiLuokka {

void Test1 () {

byte T0;

int L = 0xcafebabe; // ylin tavu (MSB) on ca (hex)

// Miten nyt T0:aan L:n alin tavu ?
// T3:een ylin tavu jne.
// onko tämä ainoa (hidas) vaihtoehto ???

T0 = (L & 255); // T0 = be (hex)

T1 = (L >>> 8) & 255;

T2 = (L >>> 16) & 255;

T3 = (L >>> 24) & 255; // T3 = ca

}

}

1. Toimiiko esittämäni javakoodi vastaavalla tavalla kuin edelläoleva delphikoodi ?


2. Aiheutuuko ongelmia siitä, että siinä missä Delphin BYTE on etumerkitön, eli arvoalueena 0..255, niin javassa byte onkin etumerkillinen, eli arvoalueena onkin -128 .. 127 (kuten Delphin ShortInt).

Kun nyt kaikki 4 esimerkissäni ollutta tavua ovat > 127, aiheutuuko tuosta ongelmia muunnoksissa (heittääkö poikkeuksia ?)

3. Onko nopeampia tapoja tehdä em.asia ?

Delphissähän tietueeseen perustuva typecastaus kääntyy suoraan muistiosoitukseksi jolloin mitään shift- tai and -operaatioita ei tarvita.

a) suoraan, kuten Delphissä

ja

b) voiko esim. edellä tuon x & 255 jättää pois,vai aiheuttaako esim tämä sijoitusyritys:

T0 = L; poikkeuksen, kun T0 on byte -tyyppiä ja L onkin int, jonka arvona on 0xcafebabe ? Tässähän yritetään (ilman tuota x & 255 -operaatiota) sijoittaa 32- bittistä arvoa 8 -bittiseen muuttujaan ?

4. Javassa ilmeisesti ainoa virallisesti etumerkitön tyyppi on 16 -bittinen char, joka on tarkoitettu unicode -merkkien käsittelyyn. Voiko kuitenkaan tehdä näin:

{
char u16;

u16 = 65535;

}

Silloin, kun tarvitaan 32 -bittisiä "bittisäiliöitä" binäärisen datan käsittelyyn, niin voiko int -tyyppiä käyttää tähän ja olla välittämättä siitä, että int on tosiasiassa etumerkillinen tyyppi, vai pitääkö homma hoitaa 64- bittisellä long -tyypillä, jolloin puolet sen kapasitetista jää käyttämättä ?

Entä merkkijonojen (String tai Stringbuffer) käyttö bittisäiliöinä, voiko javan merkkijonon merkki olla mikä hyvänsä (siis binääristä dataa, ja 16- bittisenä siis väliltä 0..65535) ?
4557
Äänestä

Muut lukivat myös

Vastaukset 4

Vanhimmat

1.   Vastaus

Java koodi toimii siten kuin delphi koodi. Koodissa pitää kuitenkin allaolevaan tapaan kertoa, että tehdään tyyppi muunnos aivan kuten C:ssä (tai muuten kääntä antaa virheen):
   
   T0 = (byte) (L & 255);


2. Vastaus

Riippuu miten käsittelet tavua. Esimerkiksi voit kirjoittaa lauseen "if (T0 < 200) ...", mutta Javassa se on aina tosi. Lukualueen rajojen ylitykset eivät luonnollisesti aiheuta poikkeuksia (eli voit kirjoittaa ilman mitään herjaa vaikka lauseen "T0 = 1000000").


3. Vastaus

Ei


3a. Vastaus

Ei



3b. Vastaus

Kyllä, kun muunnos tehdään noin päin, niin and operaatio voidaan jättää pois, (sillä pakotettu tyyppimuunnos tavallaan suorittaa sen jo, (eli vastauksessa 1 olevan esimerkin and operaatio on turha)). Toisinpäin tehtäessä and operaatio taas pitää olla, (eli silloin kun muunnat etumerkittömän tavun takaisin intiksi). Koska ilman and operaatiota etumerkki kopioituu, eli tavu 0xff (-1) muuttuukin muunnoksessa muotoon 0xffffffff (-1). Eli palautus funktio tuolle esimerkillesi olisi:

L = (T0 & 0xFF) | ((T1 & 0xFF)

Äänestä

Mainittakoon nyt vielä, että myös valmisluokkaa java.nio.ByteBuffer voi käyttää, jos haluaa jotain tavumassaa käsitellä. Siitä löytyy esim. getInt/putInt-metodit, joilla voi käsitellä neljää vierekkäistä tavua intteegerinä.

(Tosin jos haluaa vain yhdestä integeristä tavut irti, nopeusmielessä on varmaan paras vain tehdä se käsin shiftaamalla sopivasti. Ainakin gcj natiivikoodia kääntäessään näyttäisi olevan sitäpaitsi riittävän älykäs kääntämään esim. (byte)(i >> 16) yhden tavun lukemiseksi jos se on järkevää.)

Äänestä

char VOI käyttää kokonaislukuna ?!

En tiedä, kuinka yleispätevä havaintoni on, mutta seuraava esimerkkikoodi EI aiheuta poikkeuksia, ja palauttaa true !!!

Tämän perusteella näyttäisi siltä, että char -muuttujaan ja ennenkaikkea StringBuffer -luokan alkioihin (merkkeihin) VOI tallettaa mielivaltaisia kokonaislukuja väliltä 0-65535 ja ne tulevat muuttumattomina ulos.

Mutta se, että homma toimii Sunin omalla puhelinemulaattorilla: takaako se, että homma toimisi oikein muillakin laitteilla ?


----------------


static public boolean myTestA2() {
//
// static
final int maxVal = 65535;

boolean Ok;
StringBuffer St1 = new StringBuffer(65540);
int i;

// 1. initialize St1 with #0 .. #255

St1.setLength(0);
for(i=0; i

Äänestä
  • No, speksissä 'char' on listattu samassa joukossa kuin muutkin kokonaislukutyypit (kts. http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.1 esim.), joten noin maallikkona olettaisi, että se myös toimii sellaisena. En kylläkään näe suurta etua myös kaksitavuiseen "short"-tyyppiin verrattuna.

    (String- ja StringBuffer-luokista on vaikeampi olla varma, niissä kun kyse on merkkijonoksi tulkituista asioista. Luulisi char-tyyppisiä arvoja palauttavien metodien toimivan; codePointAt:n ja muiden kanssa tulee ongelmia surrogaattiparien kanssa. java.nio.CharBuffer/ShortBuffer olisivat soveltuvampia, mutta näitä ei tietysti J2ME:stä löydy. Yksinkertaiseen käyttöön ei short[]-tyyppiseen taulukkoon perustuvan luokan kirjoittelu varmaan kauheasti rasita.)

    Äänestä

Kommentoi aloitusta


Mika0800 kirjoitti:

Tyyppimuunnokset (cast) / bittikäsittely

Tyyppimuunnokset:

delphissä voi tehdä esim. näin:

type

LongRec = packed record

B0, B1, B2, B3 : Byte;

end;


procedure Test1;
var

L : Longint; // 32 bits

T0, T1, T2, T3 : Byte; // 4 tavua, 8 bit/tavu

begin

L := $cafeBabe; // ylin tavu (MSB) on ca (hex)

// alin tavu (LSB) = be (hex)

T0 := LongRec(L).B0;

T1 := LongRec(L).B1;

T2 := LongRec(L).B2;

T3 := LongRec(L).B3;

// nyt myös T0 = be (hex) ja T3 = ca (hex)

end;

Miten vastaavan voisi tehdä javalla ?

Siis esim:

class TestiLuokka {

void Test1 () {

byte T0;

int L = 0xcafebabe; // ylin tavu (MSB) on ca (hex)

// Miten nyt T0:aan L:n alin tavu ?
// T3:een ylin tavu jne.
// onko tämä ainoa (hidas) vaihtoehto ???

T0 = (L & 255); // T0 = be (hex)

T1 = (L >>> 8) & 255;

T2 = (L >>> 16) & 255;

T3 = (L >>> 24) & 255; // T3 = ca

}

}

1. Toimiiko esittämäni javakoodi vastaavalla tavalla kuin edelläoleva delphikoodi ?


2. Aiheutuuko ongelmia siitä, että siinä missä Delphin BYTE on etumerkitön, eli arvoalueena 0..255, niin javassa byte onkin etumerkillinen, eli arvoalueena onkin -128 .. 127 (kuten Delphin ShortInt).

Kun nyt kaikki 4 esimerkissäni ollutta tavua ovat > 127, aiheutuuko tuosta ongelmia muunnoksissa (heittääkö poikkeuksia ?)

3. Onko nopeampia tapoja tehdä em.asia ?

Delphissähän tietueeseen perustuva typecastaus kääntyy suoraan muistiosoitukseksi jolloin mitään shift- tai and -operaatioita ei tarvita.

a) suoraan, kuten Delphissä

ja

b) voiko esim. edellä tuon x & 255 jättää pois,vai aiheuttaako esim tämä sijoitusyritys:

T0 = L; poikkeuksen, kun T0 on byte -tyyppiä ja L onkin int, jonka arvona on 0xcafebabe ? Tässähän yritetään (ilman tuota x & 255 -operaatiota) sijoittaa 32- bittistä arvoa 8 -bittiseen muuttujaan ?

4. Javassa ilmeisesti ainoa virallisesti etumerkitön tyyppi on 16 -bittinen char, joka on tarkoitettu unicode -merkkien käsittelyyn. Voiko kuitenkaan tehdä näin:

{
char u16;

u16 = 65535;

}

Silloin, kun tarvitaan 32 -bittisiä "bittisäiliöitä" binäärisen datan käsittelyyn, niin voiko int -tyyppiä käyttää tähän ja olla välittämättä siitä, että int on tosiasiassa etumerkillinen tyyppi, vai pitääkö homma hoitaa 64- bittisellä long -tyypillä, jolloin puolet sen kapasitetista jää käyttämättä ?

Entä merkkijonojen (String tai Stringbuffer) käyttö bittisäiliöinä, voiko javan merkkijonon merkki olla mikä hyvänsä (siis binääristä dataa, ja 16- bittisenä siis väliltä 0..65535) ?

Anonyymi
5000

Ilmoita asiaton sisältö

  • Sisältää materiaalia, joka on loukkaavaa, herjaavaa, rasistista, uhkailevaa tai ahdistelevaa.

  • Materiaali sisältää nimiä, yhteystietoja tai muita henkilökohtaisia tietoja. Julkisuuden henkilöistä, julkisissa viroissa toimivista ihmisistä sekä yritysten vastuuhenkilöistä saa keskustella työhön liittyen. Myös yksityiselämään liittyvistä asioista voi keskustella siltä osin, kuin niistä on julkisesti kerrottu.

  • Sisältää lapsille haitallista tai heiltä kiellettyä materiaalia. Seksuaalinen sisältö on sallittua aiheeseen tarkoitetuilla palstoilla, joiden ikäraja on 18 vuotta.

  • Lainvastaista sisältöä voi olla mm. yksityiselämää loukkaavan tiedon levitys, kiihottaminen kansanryhmää vastaan, laiton uhkaaminen, alaikäisiin liittyvä seksuaalinen sisältö/grooming, petokset, identiteettivarkaudet, kunnianloukkaukset ja tekijänoikeusrikkomukset.

  • Sisältö ei liity palstan tai keskusteluketjun aiheeseen.

  • Viesti ei ole suomea tai ruotsia (pl. International Forums), se sisältää mainontaa, se sisältää tekijänoikeuksin suojattua materiaalia, se on massapostitus tai jokin muu syy.

Jaa keskustelu