Bitová operace
Bitová operace (anglicky bitwise operation) je operace, která aplikuje určitou logickou operaci nikoliv na jednotlivé bity, ale na celé vektory bitů; bitová negace zneguje hodnoty všech bitů operandu, bitová konjunkce (and) vrací hodnotu, jejíž n-tý bit je logickou konjunkcí n-tého bitu prvního operandu a n-tého bitu druhého operandu. Většina procesorů má strojové instrukce, které provádějí bitové operace na obvyklé operandy: byty, půlslova, slova, atd.; tyto operace typicky nejsou pomalejší než provádění sčítání a odečítání stejných operandů (protože není třeba provádět přenosy nebo výpůjčky mezi dvojkovými řády).
Dalšími bitovými operacemi, které jsou dostupné jako strojové instrukce, jsou operace bitových posuvů a rotací. Posuv o jeden bit doleva lze interpretovat jako znásobení operandu číslem dvě, posuv o jeden bit doprava jako vydělení dvěma. Posuvy o více bitů pak jako násobení nebo dělení příslušnou mocninou čísla dvě. Posuvy o jeden bit jsou mnohem rychlejší než operace násobení a dělení; posuvy o větší počet bitů se na některých procesorech provádějí opakovaným posuvem o jeden bit a mohou tak být poměrně pomalé.
V některých programovacích jazycích jsou bitové operace dostupné pomocí zvláštních operátorů. Příkladem je jazyk C a jazyky z něj odvozené.
Bitové operátory
[editovat | editovat zdroj]NOT - Bitová negace
[editovat | editovat zdroj]Bitový operátor NOT, nebo doplněk, je unární operace, která provádí logickou negaci každého bitu. Pro provedení operace je hodnota každého bitu opačná, tzn. z jednotek se stanou nuly a naopak.
NOT 0111 = 1000
V některých programovacích jazycích včetně C/C++ je bitový operátor NOT představován znakem '~' (tilda).
Pozor. Někdy se tento bitový operátor zaměňuje s logickým operátorem NOT, který je např. v C/C++ představován znakem '!' (vykřičník). Logický operátor NOT ovšem bere celou zadanou hodnotu jako jednu hodnotu typu boolean a změní hodnotu true na hodnotu false nebo naopak. Logický operátor NOT není bitovým operátorem.
OR - Bitový součet
[editovat | editovat zdroj]Bitový operátor OR bere dva bitové vzory o stejné délce a vytváří nový bitový vzor, jehož hodnota závisí na hodnotě vstupních bitových vzorů. Porovnává postupně jeden po druhém příslušné bity (první bit prvního vzoru s prvním bitem druhého vzoru, druhý bit prvního vzoru s druhým bitem druhého vzoru atd.) a provádí s každým párem logickou operaci OR. Výsledek je pak hodnota 1, pokud alespoň jeden bit (nebo také oba dva) mají hodnotu 1, nebo je výsledek hodnota 0, pokud oba dva bity mají hodnotu 0. Příklad:
0101 OR 0011 = 0111
V jazycích C/C++ je bitový operátor OR představován znakem '|' (pozn. nezaměňovat s logickým operátorem OR, který je přestavován dvojicí těchto znaků '||').
XOR - Bitová nonekvivalence
[editovat | editovat zdroj]Bitový operátor XOR bere dva bitové vzory o stejné délce a vytváří nový bitový vzor, jehož hodnota závisí na hodnotě vstupních bitových vzorů. Porovnává postupně jeden po druhém příslušné bity (první bit prvního vzoru s prvním bitem druhého vzoru, druhý bit prvního vzoru s druhým bitem druhého vzoru atd.) a provádí s každým párem logickou operaci XOR. Hodnota bitu na dané pozici ve výsledku je 1, pokud jsou hodnoty bitů na téže pozici ve stupních bitových vzorech různé, jinak je hodnota bitu ve výsledku 0. Příklad:
0101 XOR 0011 = 0110
V jazycích C/C++ je bitový operátor XOR představován znakem '^' (stříška).
V assembleru se používá operace XOR pro rychlé nastavení registru na nulovou hodnotu tím, že jsou obě vstupní hodnoty operace stejné. Příklad:
XOR AX, AX
Na některých architekturách tato operace vyžaduje méně cyklů CPU než např. naplnění registru hodnotou 0. Příklad:
MOV AX, 0
Takže je na některých architekturách operace XOR rychlejší.
AND - Bitový součin
[editovat | editovat zdroj]Bitový operátor AND bere dva bitové vzory o stejné délce a vytváří nový bitový vzor, jehož hodnota závisí na hodnotě vstupních bitových vzorů. Porovnává postupně jeden po druhém příslušné bity (první bit prvního vzoru s prvním bitem druhého vzoru, druhý bit prvního vzoru s druhým bitem druhého vzoru atd.) a provádí s každým párem logickou operaci AND. Hodnota bitu na dané pozici ve výsledku je 1, pokud jsou hodnoty bitů na téže pozici v obou vstupních bitových vzorech 1, jinak je hodnota bitu na dané pozici ve výsledku 0. Příklad:
0101 AND 0011 = 0001
V jazycích C/C++ je bitový operátor AND představován znakem '&' (pozn. nezaměňovat s logickým operátorem AND, který je představován dvojicí těchto znaků '&&').
Bitový posuv
[editovat | editovat zdroj]
Posuv (u některých autorů posun) doleva se v programovacích jazycích C, C++, C# zapisuje pomocí binárního operátoru << (druhý operand udává počet bitů posuvu). Komplementární posuv doprava pomocí >>.
Posuv doleva o n pozic odpovídá vynásobení mocninou dvojky podle vztahu: .
Posuv doprava o n pozic odpovídá vydělení mocninou dvojky podle vztahu: , kde / má význam celočíselné dělení.
U posuvu doprava rozlišujeme tak zvaný aritmetický a logický posuv. Aritmetický posuv odpovídá dělení dvěma čísla se znaménkem zobrazených pomocí dvojkového doplňku, logický posuv dělení dvěma čísla bez znaménka. Zatímco u logického posuvu se na místo nejvyšších bitů nasouvají nuly, u aritmetického posuvu se hodnota nejvyššího bitu zachovává.
U posuvu doleva lze použít stejnou operaci pro čísla se znaménkem i bez znaménka. Rozdíl je v tom, jak se vyhodnocuje přetečení; pro čísla se znaménkem by se měl vyhodnocovat příznak přetečení u čísel bez znaménkem příznak přenosu. U posuvů o více bitů by se jako přetečení mělo hodnotit přetečení při libovolném dílčím posuvu o jeden bit.
Vyšší programovací jazyky obvykle přetečení při bitových posuvech ignorují stejně jako při aritmetických operacích.
Aritmetický posuv
[editovat | editovat zdroj]
![](http://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Rotate_left_logically.svg/150px-Rotate_left_logically.svg.png)
![](http://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Rotate_right_arithmetically.svg/150px-Rotate_right_arithmetically.svg.png)
Ve třetím příkladě dochází ke zdvojení nejvyššího bitu (po posuvu je jeho hodnota ve druhém nejvyšším bitu a zároveň zůstane i nejvyšším bitu):
00010111 POSUV O JEDNU POZICI DOLEVA = 00101110 00010111 POSUV O JEDNU POZICI DOPRAVA = 00001011 10010111 POSUV O JEDNU POZICI DOPRAVA = 11001011 00010111 POSUV O DVĚ POZICE DOLEVA = 01011100
Logický posuv
[editovat | editovat zdroj]
![](http://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Rotate_right_logically.svg/150px-Rotate_right_logically.svg.png)
![](http://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Rotate_left_logically.svg/150px-Rotate_left_logically.svg.png)
Ve třetím příkladě se nejvyšší bit posune na místo druhého nejvyššího bitu a na místo nejvyššího bitu se nasune nula:
00010111 POSUV O JEDNU POZICI DOLEVA = 00101110 00010111 POSUV O JEDNU POZICI DOPRAVA = 00001011 10010111 POSUV O JEDNU POZICI DOPRAVA = 01001011 00010111 POSUV O DVĚ POZICE DOLEVA = 01011100
Bitové rotace
[editovat | editovat zdroj]![]() |
![]() |
![]() |
![]() |
Bitové rotace se podobají bitovým posuvům, rozdílem je, že bit, který je při posuvu vysouván z hodnoty ven, je při rotaci opět vkládán na opačném konci. Tato operace nebývá dostupná ve vyšších programovacích jazycích, je však ve strojovém kódu mnoha procesorů. U mikroprocesorů Intel mají rotace dvě varianty: v jedné rotují pouze bity operandu, ve druhé jsou rotující bity doplněny o příznak přenosu (anglicky carry flag). V obou případech se příznak přenosu nastavuje na hodnotu bitu, který byl vysunut ven z operandu (což na prvních dvou obrázcích není znázorněno).
Srovnání logických a bitových operátorů v jazyce C
[editovat | editovat zdroj]V jazyce C lze bitové i logické operace provádět s libovolnými celočíselnými typy. Bitové operace je třeba dobře rozlišovat od logických (které interpretují nulu jako nepravdu a libovolnou nenulovou hodnotu jako pravdu):
Operace | Logický operátor | Bitový operátor |
---|---|---|
Negace (not) | ! | ~ |
Konjunkce (and) | && | & |
Disjunkce (or) | || | | |
Nonekvivalence (xor) | (není) | ^ |
Místo chybějícího logického operátoru nonekvivalence lze použít např. (a == 0) != (b == 0)
.