Ok, varmastikin laaja aihe tämäkin. Mutta pienessä päässäni pyörii näinä sateisina syysil... kesäiltoina, että mitä käyttöä näille bittioperaattoreille on? Kiinnostaisi äärettömästi tietää, että miten hyödyntää ja käyttää näitä. Esimerkiksi SDL:n initialisointifunktiossa (muistaakseni) käytetään |-operaattoria, kuten myös Sqwiikin mainiossa Erkki-enginessä.
Miksi tehdä tuollaisia vertailuja? (Vai mitä nyt sitten ovatkaan) Miksi käyttää niitä, ja kun niitä käyttää, niin millaisissa tilanteissa ja tietysti miten? Mitä hyötyä näillä (|, &, ^, jne.) voisin itse saavuttaa? (Ok, nuo kysymykset ovat vähän epämääräisiä...) Etsiskelin näistä jonkinlaisia oppaita ja tutoriaaleja, mutta ei sattunut silmään ja nyt sitten päädyin kysymään asiasta täällä.
Eli aika uuno-tasolta lähden näitä ihmettelemään.
Bittioperaattoreilla pystyy nopeasti vertaamaan/muuttamaan luvun/tms bittejä. Niillä voi myös kikkailla jos haluaa luvun ehdottomasti rajattua johonkin.
Esim. nopea tarkistus onko (kokonais)luku pariton:
if(luku & 1)printf("on pariton");
..joka johtuu siitä, että 2-järjestelmässä bitti 1 on ainoa joka saa arvon 1. Muilla sitten 2, 4, 8, 16 jne
Bittioperaatiolla | (or) saadaan esimerkiksi tavalliseen int-arvoon (Integer, Longint) 32 eri on/off-arvoa siinä tapauksessa, että ei haluta käyttää bool-muuttujia (Boolean). On mielestäni helpompaa kirjoittaa ensimmäinen kuin jälkimmäinen vaihtoehto (kuten oikeasti tehdäänkin):
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_ALPHABITDEPTH | DDSD_PIXELFORMAT;
ddsd.dwFlags.dwCaps = true; ddsd.dwFlags.dwWidth = true; ddsd.dwFlags.dwHeight = true; ddsd.dwFlags.dwAlphaBitDepth = true; ddsd.dwFlags.ddpfPixelFormat = true;
En nyt jaksa selittää mikä tämä koodi oikeasti on ja miten se toimii, mutta ymmärrät varmaankin hyödyn?
Metabolix kirjoitti:
En nyt jaksa selittää mikä tämä koodi oikeasti on ja miten se toimii, mutta ymmärrät varmaankin hyödyn?
ddsd = Direct Draw Surface Descriptor tjsp. :)
juu sepä se
Jos nyt vielä selitetään miten noita voisi käyttää juuri noissa flageissä hyödyksi...
Eli jos tarvitset paljon bittiflageja (joista usea voi olla samaan aikaan päällä) voit tosiaan käyttää bittioperaatioita mukavasti hyödyksesi.
Eli jokainen flagi määritellään tähän tyyliin:
#define MY_DOG_FLAG (1 << 0) #define MY_CAT_FLAG (1 << 1) #define MY_HEDGEHOG_FLAG (1 << 2) #define MY_COW_FLAG (1 << 3) // jne, flagit ovat 2:n potensseja
Nyt voitkin tunkea noiden flagien yhdistelmiä vaikkapa unsigned int:iin OR-operaattorilla (joka tavallaan vain pistää tietyn bitin päälle):
unsigned int animals = MY_CAT_FLAG | MY_COW_FLAG;
AND-operaattorilla voit testata onko jokin bittiflagi päällä:
if(animals & MY_HEDGEHOG_FLAG) printf("minä pistän siiliä\n");
AND-tavallaan siis vain maskaa esille vain tietyn bitin (tai tietyt bitit) arvosta.
Jos haluat vaihtaa jonkun flagin ykkösestä nollaksi tai päinvastoin, voit käyttää XOR-operaattoria. Ei siis tarvitse tietää mikä oli flagin alkuperäinen arvo:
animals ^= MY_DOG_FLAG;
Noniin, vihdoinkin taidan ymmärrän noiden bittien liikuttelun hyödyn. Eli: 1 << 6 == siirtänee ykköstä kuuden (minkä? bitin?) verran vasemmalle, jolloin se on 1 0000?
Eli tuon
unsigned int animals = MY_CAT_FLAG | MY_COW_FLAG;
jälkeen animals on binäärilukuna 1010? No joka tapauksessa, tästähän alkaa jo pieniä ideoita kolisemaan pääkoppaan näiden käytön ymmärtämisen lisääntyessä :). Kiitoksia neuvoista.
Juu, << shiftaa tietyn bittimäärän verran vasemmalle, tosin 1 << 6 on kylläkin 100 0000. Tuo animals-homma meni oikein.
Ennen vanhaan shiftejä (<< ja >>) käytettiin myöskin nopeana tapana laskea kerto- ja jakolaskuja jotka olivat kahden potensseja (tai jaettiin joku ei-kahden-potenssi kahden potensseihin ja sitten shiftailtiin). Nykyisin kääntäjät osanneevat valita parhaan kerto-/jakolaskutavan joten tuskin niitä enää kannattaa siihen käyttää.
Mistäköhän muuten johtuu, että kun kutsuin funktiota tyyliin
funktio(arvo1, arvo2 ^ 3, arvo3);
ohjelma toimi eri lailla, kuin jos muutin kutsun muotoon
funktio(arvo1, (arvo2 ^ 3), arvo3);
eli lisäsin vain sulut? Muistaakseni jälkimmäinen tuntui toimivan oikein, vaikka kaiken järjen mukaanhan niissä ei pitäisi olla mitään eroa.
mutta mm. mobiiliohjelmoinnissa (symbian/c++) näitä binäärikertolaskuja ( >> ja << )kannattaa vielä käyttää, koska kännyköissä ei ole aritmetiikkaprosessessoria, ja tehokkaasti optimoituja ALU-yksiköitä.
Sulautettu softa sisältänee eniten yksittäisten bittien viilaamista. Monesti esimerkiksi jotain led-ryhmää ohjataan siten, että yksi bitti vastaa yhtä lediä. Scrollaava teksti tällaiseen led-patteriin onkin kätevä tehdä bittejä shiftaamalla.
On monia sovelluskohteita, jossa muistia/tehoa/virtaa ei ole liikaa käytettävissä, vaan hommat pitää hoitaa tiiviillä ja tehokkaalla tavalla. Turhaa kikkailua kannattaa silti välttää.
Putkasta löytyi yksi koodivinkkikin.
Aihe on jo aika vanha, joten et voi enää vastata siihen.