Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
Učíme se C (25. díl) - Bitové operátory a bitové pole
28. května 2001, 00.00 | Dnes o tom, jaké jazyk C nabízí operátory a datové struktury pro
práci s bity, k čemu tyto operátory slouží a jak se používají.
Bitové operátory a bitové pole
Protože jazyk C je oproti jiným vyšším jazykům zaměřen na přeci jen poněkud nižší úroveň, nabízí programátorům i operátory, pomocí kterých mohou nepřímo pracovat i s jednotlivými bity.
V následujícím textu budu předpokládat znalost některých základních booleových funkcí jako je AND, OR apod.
bitový součin - &
První z operátorů, na které se dnes podíváme, je operátor bitového součinu. Tento operátor provede logickou operaci AND mezi všemi bity svých operandů a takto vzniklá hodnota bude i výsledkem celé operace. Nejlépe si to demonstrujeme rovnou na příkladu:
77 & 198
Výslednou hodnotou tohoto výrazu bude číslo 68. Pro lepší pochopení se podívejme přímo na binární zápisy těchto hodnot.
77 01001101
198 11000110
68 01000100
Operandy operátoru binárního součinu mohou být pouze výrazy celočíselného typu, není tedy možné provádět bitový součin s hodnotami typu float, double ani long double.
Jedno z možných použití operátoru & si můžeme demonstrovat na příkladu, ve kterém si zkusíme vytvořit jednoduché makro, které zjistí, zda je jemu předaný argument lichý či sudý.
#define liche(x) (1 & (x))
bitový součet - |
Existuje-li v C operátor bitového součinu, jistě bude implementována i operace bitového součtu. Tu provádí operátor |, který má, až na to, že s bity provádí operaci OR, stejné vlastnosti jako operátor &. V příkladu použijeme stejné hodnoty jako minule.
77 | 198 == 207
77 01001101
198 11000110
207 11001111
bitový exklusivní součet - ^
Oba předchozí operátory doplňuje ještě jeden podobný, který s jednotlivými bity svých operandů provádí operaci XOR.
77 ^ 198 == 139
77 01001101
198 11000110
139 10001011
bitová negace - ~
Na rozdíl od předchozích operátorů je bitová negace unárním operátorem, tedy má pouze jeden operand. Ten musí být, stejně jako v předchozích případech, celočíselného typu. Při provádění operace jsou postupně všechny jeho bity negovány a takto získaná hodnota je výsledkem použití operátoru. V následujícím příkladu uvažujeme typy unsigned char. V případě použití typu signed by ještě hrál roli negovaný znaménkový bit.
~77 == 178
77 01001101
178 10110010
Protože jsou negovány všechny bity čísla, včetně počátečních nul, znamená to, že pro operandy se stejnou hodnotou, ale různým typem (char, short, int, long int), bude výsledná hodnota různá.
bitový posun doleva - <<
Tímto operátorem jednoduše provedeme posun všech bitů levého operandu o určitý počet míst, který udává hodnota pravého operandu. Při posunu se bity nejvíce nalevo ztrácejí a zleva jsou uvolněná místa doplněna nulami. Následující příkaz vrátí o dvě místa bitově posunutou hodnotu čísla 45.
45 << 2;
před posunem (hodnota 45) | 00101101 |
po posunu (hodnota 180, výsledek celého výrazu) | 10110100 |
Bitový posun doleva se často používá k provádění násobení mocninami dvou. Tento způsob je totiž znatelně rychlejší než normální násobení. Platí, že x << n == x*2n. Schopnější překladače dnes již samy nahrazují (je li to možné) obyčejné násobení bitovým posunem.
bitový posun doprava - >>
Komplementární operací k bitovému posunu doleva je bitový posun doprava. V tomto případě se bity zprava ztrácí a zleva jsou doplňovány nulou u neznaménkových typů, nebo znaménkovým bitem u typů znaménkových, což je ale implementačně závislé. Stejně jako se dal bitový posun doleva použít k násobení, lze zase bitový posun doprava použít k celočíselnému dělení mocninami dvou. x >> n == x/2n
48 >> 4 == 3
přiřazovací bitové operátory
Jak je v C zvykem, i k bitovým operátorům existují jejich verze kombinující v sobě přiřazení, a proto můžeme některé zápisy zkrátit pomocí následujících operátorů:
&=
|=
^=
<<=
>>=
bitové pole
Bitové pole je datový objekt podobný typu struct, kde ale lze pro každou položku definovat i její velikost v bitech, což lze využít například potřebujeme-li šetřit pamětí, nicméně je nutné si uvědomit, že celková velikost bude vždy zarovnána na násobek sizeof(int). Typy položek bitového pole jsou omezeny pouze na typ int (signed i unsigned) a velikost každé z nich nesmí překročit počet bitů alokovaných typem int.
Deklarace bitového pole je v podstatě totožná s deklarací obyčejné struktury, pouze přibude informace o počtu bitů obsazených jednotlivými jeho položkami. Ani přístup k položkám nebude v případě bitového pole odlišný od způsobů používaných při práci s typem struct. Ukažme si to na následujícím příkladu:
|
V příkladu použité bitové pole CLOVEK pro jednoduchost nepodporuje přílišnou dlouhověkost ani nadváhu. :)
Proměnná osoba1 bude v paměti uložena takto(směr ukládání je ovšem implementačně závislý):
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
pohlavi | vaha | vek |
Při definování jednotlivých položek bitového pole je možné neuvést identifikátor položky. Taková položka pak nebude přístupná přes žádný identifikátor, pouze jí bude vyhrazeno příslušné místo. Např.
|
V případě, že by některá z položek přesahovala za hranici velikosti typu int, bude zarovnána na začátek této hranice. Pokud bychom uvažovali sizeof(int)==2, v příkladu výše by se to týkalo položky vek, která by o jeden bit překročila hranici velikosti typu int. Proto celá tato struktura zabírá 2*sizeof(int) místa. Zarovnání na další hranici int lze také vynutit přidáním položky nulové délky.
Obsah seriálu (více o seriálu):
- Učíme se C (1. díl)
- Učíme se C (2. díl)
- Učíme se C (3.díl)
- Učíme se C (4. díl)
- Učíme se C (5.díl)
- Učíme se C (6.díl)
- Učíme se C (7.díl)
- Učíme se C (8.díl)
- Učíme se C (9.díl) - Řetězce
- Učíme se C (10.díl) - Vstupně výstupní funkce
- Učíme se C (11.díl) - Formátovaný výstup
- Učíme se C (12.díl) - Formátový specifikátor
- Učíme se C (13.díl)
- Učíme se C (14.díl) - Vícerozměrná pole
- Učíme se C (15.díl) - Ukazatele
- Učíme se C (16.díl) - Modifikátory paměťové třídy
- Učíme se C (17.díl) - Pole a ukazatel
- Učíme se C (18. díl) - Dynamická alokace paměti
- Učíme se C (19. díl) - Práce se soubory I.
- Učíme se C (20. díl) - Práce se soubory II.
- Učíme se C (21. díl) - Parametry funkce main()
- Učíme se C (22. díl) - Ukazatele na funkce
- Učíme se C (23. díl) - Složité deklarace a definice
- Učíme se C (24. díl) - Funkce s proměnným počtem parametrů
- Učíme se C (25. díl) - Bitové operátory a bitové pole
- Učíme se C (26. díl) - Datové typy enum a union
- Učíme se C (27. díl - závěr) - Programové moduly
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007