Operacije sa bitovima u progamskom jeziku C

Logički operatori u programskom jeziku C (&&, ||, ^^ i !) standardno uzimaju u obzir celu promenljivu, pri čemu se vrednost 0 računa kao "DA", ili "TAČNO", dok se bilo koja vrednost različita od 0 (ne samo 1), računa kao "NE", ili "NETAČNO" i, pri tome, nije moguće pristupati pojedinačnim bitovima (mada, možda bi se neko upitao zašto bismo to uopšte i radili).

U većini uobičajenih situacija nije neophodno pristupati bitovima, ali, u nekim specifičnim situacijama, to je jedino rešenje. Na primer, kada želimo da promenimo ili ispitamo određeni pin (kontakt koji u datom trenutku ima vrednost 0, ili 1) na nekom od računarskih portova, ili nekog specijalizovanog uređaja koji je priključen na računar.

U programskom jeziku C, ovo se postiže upotrebom specijalizovanih logičkih operatora koji operišu nad pojedinim bitovima neke promenljive.

Bitovski operatori nisu u stanju da obave operaciju samo na jednom paru bitova, već operišu nad svim parovima susednih bitova u dve promenljive koje učestvuju u operaciji. Ovo može delovati problematično (i svakako zaslužuje pažnju), ali, uz pažljivo promišljanje možemo uvek postići željeni rezultat.

Upoznajmo se sa načinom funkcionisanja samih operatora.

Operator & (logičko I)

Tablica istinitosti za logičku konjukciju (logičko I) data je na sledećoj slici:

Logičko I - Tablica Istinitosti
Slika 1. - Logičko I daje vrednost "TAČNO", samo kada su oba uslova zadovoljena

Logički operator & koji operiše nad dve celobrojne vrednosti nezavisno primenjuje datu tablicu na susedne parove bitova (u našim primerima, celobrojne vrednosti su osmobitne), dajući pri tom sledeći rezultat:

Logičko I - Primer
Slika 2. - Logička konjukcija primenjuje se na svaki par bitova nezavisno. Rezultat će biti 1 samo tamo gde oba bita imaju vrednost 1.

Operator | (logičko ILI)

Tablica istinitosti za logičku disjunkciju (logičko ILI) izgleda ovako:

Logičko ILI - Tablica Istinitosti
Slika 3. - Logičko ILI daje vrednost "TAČNO", onda kada je bilo koji od dva uslova zadovoljen

Kao i u prethodnom slučaju, logički operator | operiše nad dve celobrojne vrednosti i nezavisno primenjuje gornju tablicu na susedne parove bitova.

Logičko ILI - Primer
Slika 4. - Logička disjunkcija, primenjena na svaki par bitova nezavisno, daje rezultat 1 na svim mestima gde makar jedan od dva bita ima vrednost 1.

Operator ^ (isključivo ILI)

Na donjoj slici, data je tablica istinitosti za operaciju ekskluzivne disjunkciju (isključivo ILI):

Isključivo ILI - Tablica Istinitosti
Slika 5. - Ekskuzivna disjunkcija daje vrednost "TAČNO" samo na onim mestima gde su operandi različiti

Kada gornju tablicu primenimo na dve celobrojne vrednosti, dobijamo sledeći rezultat:

Isključivo ILI - Primer
Slika 6. - U skladu sa tablicom isključive disjunkcije, operator ^ daje vrednost 1 samo na onim mestima gde par bitova sadrži jednu nulu i jednu jedinicu.

Pomeranje bitova ulevo - <<

Operacija a << n pomera sve bitove promenljive a za n mesta ulevo, pri čemu se broju, sa desne strane, dopisuju nule. Primer: Ukoliko promenljiva a na početku ima vrednost 1, posle operacije a << 2, imaće vrednost 4.

Pomeranje bitova ulevo - Primer
Slika 7. - Pomeranje bitova ulevo za dva mesta (bitovi koji ne mogu biti smešteni sa leve strane nestaju, a desno se dopisuju nule)

U praktičnom smislu, upotrebom ovog operatora možemo lako pomnožiti neku vrednost bilo kojim od stepena dvojke.

Pri upotrebi ovog operatora moramo uvek voditi računa o tome šta se dešava sa leve strane. Ukoliko pomeramo bitove, lako se može desiti (kao u slučaju sa gornje slike), da neke od njih praktično izbrišemo!

Pomeranje bitova udesno - >>

Operacija a >> n pomera sve bitove promenljive a za n mesta udesno, pri čemu se broju, sa leve strane, dopisuju nule. Ukoliko promenljiva a na početku ima vrednost 8, posle operacije a >> 2 imaće vrednost 2.

Pomeranje bitova udesno - Primer
Slika 8. - Pomeranje bitova ulevo za dva mesta (bitovi koji ne mogu biti smešteni sa leve strane nestaju, a desno se dopisuju nule)

Upotrebom ovog operatora možemo lako podeliti neku vrednost bilo kojim od stepena dvojke.

Kao i u slučaju prethodnog operatora pomeranja (ulevo), pri upotrebi operatora pomeranja bitova udesno, takođe moramo uvek voditi računa o tome šta se dešava, ovoga puta, sa desne strane. Ukoliko pomeramo bitove, lako se može desiti da neke od njih praktično izbrišemo, ali, s obzirom na to da (praktično) obavljamo celobrojno deljenje (što nam je najverovatnije i bila namera), to i nije preveliki problem.

Maskiranje bitova

Da bismo mogli da pristupimo određenom bitu, moramo ga "maskirati", to jest izolovati, tako da postignemo da logički operator koji koristimo utiče samo na poziciju uključenog bita.

Ovo se postiže upotrebom operatora pomeranja ulevo:

a = a << (p - 1);

Maskiranje bitova - Primer
Slika 9. - Pomeranjem bitova za četiri mesta vrlo lako dobijamo stepen dvojke koji nam je potreban za "gađanje" bita na određenoj poziciji (mnogo lakše, nego da ga računamo, recimo, preko zasebne funkcije)

.... gde je p pozicija koju "gađamo".

Pogledajmo sada šta možemo postići upotrebom ove tehnike.

Očitavanje vrednosti određenog bita

Ukoliko želimo da očitamo vrednost nekog bita (proverimo da li ima vrednost 0 ili 1), upotrebićemo sledeću proceduru (na primer, želimo da očitamo 4 bit sa desne strane):

Prvo ćemo, koristeći operator pomeranja bitova udesno, dovesti četvrti bit na prvu poziciju:

Očitavanje vrednosti bita - Maskiranje
Slika 10. - Ako tražimo vrednost bita na 4. poziciji, potrebno je bitove pomeriti tri mesta udesno.

Potom, koristeći operator logičke konjukcije, svodimo rezultat na 0 ili 1.

Očitavanje vrednosti bita - Primer
Slika 11. - Logičko I svešće rezultat na 0 ili 1.

Da pojasnimo: logičko I (konjukcija), svešće sve bitove u rezultatu osim prvog na nulu (svi bitovi broja 1, osim prvog, su 0). Rezultat stoga zavisi od vrednosti bita na prvoj poziciji. Ukoliko je on 1, rezultat će biti 1 (i obrnuto).

Uključivanje određenog bita

Da bismo određeni bit uključili (postavili njegovu vrednost na 1), maskiraćemo njegovu poziciju ....

Uključivanje bita - Maskiranje
Slika 12. - Pravimo "masku" pomeranjem uključenog bita na poziciju p

.... i potom pozvati operator logičke disjunkcije (ILI)

Uključivanje bita - Primer
Slika 13. - Logička konjukcija isključiće obavezno sve bitove osim prvog, tako da se krajnji rezultat svodi na vrednost prvog bita.

Svi bitovi, osim maskiranog, zadržaće svoje vrednosti, dok će maskirani bit posle izvršavanje operacije sigurno imati vrednost 1.

Isključivanje određenog bita

Da bismo određeni bit isključili, prvo ćemo napraviti standardnu masku kao i do sada ....

Isključivanje bita - Maskiranje
Slika 14. - I ovoga puta pravimo "masku" pomeranjem uključenog bita na poziciju p, ali ćemo je za potrebe operacije isključivanja bita, prethodno invertovati.

.... pa je zatim invertovati (promeniti vrednost svih bitova, tako da nule postanu jedinice, a jedinice nule, upotrebom operatora ~) i potom pozvati operator konjukcije (logičko I)

Isključivanje bita - Primer
Slika 15. - Upotrebom invertovane maske, svi uključeni bitovi će ostati uključeni, dok će uključeni bit na poziciji p postati uključen, dok će isključeni bit na poziciji p ostati isključen.

"Obrtanje" bita na poziciji n

Za promenu vrednosti bita, posle maskiranja....

Obrtanje bita - Maskiranje
Slika 16. - Pravimo "masku" pomeranjem uključenog bita na poziciju p

.... pozvaćemo bitovski operator XOR

Obrtanje bita - Primer
Slika 17. - Svi bitovi koji su imali vrednost 1, zadržavaju tu vrednost, zato što se "xor-uju" sa nulama na svim pozicijama osim 4. Na četvrtoj poziciji XOR uključuje bit, ako je bit bio 0, ili ga isključuje, ako je bio 1.

Deluje jednostavno (zapravo i jeste) i reklo bi se da je operator XOR smišljen upravo za ovako nešto?

Zapravo jeste, ali, pored ovoga, operator XOR ima i brojne druge primene, o čemu ćemo pisati u nekom od narednih članaka ....

Napomena: Tekstovi i slike na sajtu www.skola-programiranja.rs (osim u slučajevima pojedinih fotografija, gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta www.skola-programiranja.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo korišćenje u komercijalne svrhe, bez eksplicitnog odobrenja autora i Računarskog centra SystemPro. ©SystemPro d.o.o. novembar 2019.
Autor članka Nikola Vukićević Za web portal www.skola-programiranja.rs Preuzeto sa sajta www.codeblog.rs uz odobrenje autora
Podelite sa prijateljima: