Bitové operace v C - Bitwise operations in C
![]() | tento článek je napsán jako manuál nebo průvodce.Březen 2015) (Zjistěte, jak a kdy odstranit tuto zprávu šablony) ( |
V Programovací jazyk C., operace lze provádět na a bitová úroveň použitím bitové operátory.
Bitové operace jsou porovnány s na úrovni bajtů operace, které charakterizují logické protějšky bitových operátorů, operátory AND, OR a NOT. Místo toho, aby operovali na jednotlivých bitech, operátoři na úrovni bajtů pracují na řetězcích osmi bitů (známých jako bajty) najednou. Důvodem je to, že bajt je obvykle nejmenší jednotka adresovatelné paměti (tj. Data s jedinečným adresa paměti ).
To platí i pro bitové operátory, což znamená, že i když pracují pouze s jedním bitem, nemohou jako vstup přijmout nic menšího než bajt.
Všichni tito operátoři jsou také k dispozici v C ++, a mnoho C-rodina jazyky.
Bitové operátory
C poskytuje šest operátory pro bit manipulace.[1]
Symbol | Operátor |
---|---|
& | bitové AND |
| | bitové včetně NEBO |
^ | bitový XOR (exkluzivní OR) |
<< | levý Shift |
>> | pravý posun |
~ | bitový NOT (něčí doplněk) (unární) |
Bitové AND &
trochu a | bit b | a & b (a AND b) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
Bitový operátor AND je jediný ampersand: &
. Je to jen reprezentace AND, která pracuje spíše na bitech operandů než na hodnotě pravdivosti operandů. Bitový binární AND dělá logické A (jak je uvedeno v tabulce výše) bitů na každé pozici čísla v binární formě.
Například práce s bajtem (typ char):
11001000 & 10111000 -------- = 10001000
The nejvýznamnější bit prvního čísla je 1 a číslo druhého čísla je také 1, takže nejvýznamnější bit výsledku je 1; ve druhém nejvýznamnějším bitu je bit druhého čísla nula, takže máme výsledek jako 0. [2]
Bitové NEBO |
trochu a | bit b | a | b (a NEBO b) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Podobně jako bitový AND, bitový OR funguje pouze na bitové úrovni. Výsledkem je 1, pokud je jeden z bitů 1 a nula, pouze když jsou oba bity 0. Jeho symbol je |
kterou lze nazvat dýmkou.
11001000 | 10111000 -------- = 11111000
Bitový XOR ^
trochu a | bit b | a ^ b (a XOR b) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Bitový XOR (exkluzivní nebo) provádí logickou XOR funkci, která je ekvivalentní přidání dvou bitů a vyřazení carry. Výsledek je nulový, pouze když máme dvě nuly nebo dvě.[3] XOR lze použít k přepínání bitů mezi 1 a 0. Tedy i = i ^ 1
při použití ve smyčce přepíná jeho hodnoty mezi 1 a 0.[4]
11001000 ^ 10111000 -------- = 01110000
Bitové NENÍ ~
/ doplněk jedniček (unární)
trochu a | ~ a (doplněk a) |
---|---|
0 | 1 |
1 | 0 |
Doplněk těch (~
) nebo bitový doplněk nám získá doplněk daného čísla. Tak dostaneme bity invertované, pro každý bit 1
výsledek je bit 0
a naopak za každý bit 0
máme trochu 1
. Tuto operaci nelze zaměňovat logická negace !
.
~ 11001000 -------- = 00110111
Operátoři směn
Existují dva operátoři bitového posunu. Oni jsou
- Pravý posun (
>>
) - Levý Shift (
<<
)
Pravý posun >>
Symbol operátora pravého posunu je >>
. Pro svůj provoz vyžaduje dva operandy. Posune každý bit v jeho levém operandu doprava. Počet následujících za operátorem určuje počet míst, kde se bity posunou (tj. Pravý operand). ch >> 3
všechny bity budou posunuty doprava o tři místa atd.
Příklad:
- Pokud proměnná
ch
obsahuje bitový vzor11100101
, pakch >> 1
přinese výsledek01110010
, ach >> 2
bude vyrábět00111001
.
Zde se nalevo generují mezery, když se bity posunou doprava. Při provádění na nepodepsaném typu je provedená operace a logický posun, což způsobí, že mezery budou vyplněny 0
s (nuly). Při provádění na podepsaném typu je výsledek technicky nedefinovaný a závisí na kompilátoru,[5] nicméně většina překladačů provede aritmetický posun, což způsobilo, že mezera byla vyplněna bitem znaménka levého operandu.
Pravý posuv lze použít k rozdělení bitového vzoru o 2, jak je znázorněno:
i = 14; // Bitový vzor 00001110j = i >> 1; // zde máme bitový vzor posunutý o 1, takže dostaneme 00000111 = 7, což je 14/2
Využití operátora pravého posunu
Typické použití operátoru posunu doprava v C lze vidět z následujícího kódu.
Příklad:
#zahrnout <stdio.h> prázdnota ukázky( nepodepsaný int X ){ int i=0; pro (i = (velikost(int) * 8) - 1; i >= 0; i--) { putchar(X & (1u << i) ? '1' : '0'); } printf(" n");}int hlavní( prázdnota ){ int j = 5225; printf("% d v binárním formátu t t ", j); / * Předpokládejme, že máme funkci, která po zadání vytiskne binární řetězec desítkové celé číslo */ ukázky(j); / * smyčka pro pravou směnu * / pro (int m = 0; m <= 5; m++) { int n = j >> m; printf("% d pravý posun% d dává", j, m); ukázky(n); } vrátit se 0;}
Výstupem výše uvedeného programu bude
5225 v binárním 000000000000000000010100011010015225 pravém posunem 0 dává 000000000000000000010100011010015225 posunutí vpravo 1 dává 000000000000000000001010001101005225 posunutí vpravo 2 dává 000000000000000000000101000110105225 posunutí vpravo 3 dává 000000000000000000000010100011015225 posunutí vpravo 4 dává 000000000000000000000001010001105225 posunutí vpravo 5 umožní 00000000000000000000000010100011
Levý Shift <<
Symbol operátora levého posunu je <<
. Posune každý bit ve svém levém operandu doleva o počet pozic označených pravým operandem. Funguje to opačně než u operátora pravého posunu. Tím, že dělá ch << 1
ve výše uvedeném příkladu máme 11001010
Generované prázdné mezery jsou vyplněny nulami, jak je uvedeno výše.
Levý posun lze použít k vynásobení celého čísla mocninami 2 jako v
int i = 4; / * ekvivalent bitového vzoru je binární 100 * /int j = i << 2; / * dělá to binární 10 000, což vynásobí původní číslo o 4, tj. 16 * /
Příklad: jednoduchý sčítací program
Následující program přidá dva operandy pomocí AND, XOR a levého posunu (<<).
#zahrnout <stdio.h>int hlavní( prázdnota ){ nepodepsaný int X = 3, y = 1, součet, nést; součet = X ^ y; // x XOR r nést = X & y; // x AND y zatímco (nést != 0) { nést = nést << 1; // posun levého nosiče X = součet; // inicializuje x jako součet y = nést; // inicializovat y jako carry součet = X ^ y; // součet se vypočítá nést = X & y; / * carry se počítá, podmínka smyčky je vyhodnotí a postup se opakuje do carry se rovná 0. */ } printf("% u n", součet); // program vytiskne 4 vrátit se 0;}
Bitové operátory přiřazení
C poskytuje operátor složeného přiřazení pro každého binární aritmetická a bitová operace (tj. každá operace, která přijímá dva operandy). Každý z operátorů složeného bitového přiřazení provede příslušnou binární operaci a uloží výsledek do levého operandu.[6]
Operátory bitového přiřazení jsou následující:
Symbol | Operátor |
---|---|
&= | bitové AND přiřazení |
|= | bitové inkluzivní NEBO přiřazení |
^= | bitové exkluzivní přiřazení OR |
<<= | přiřazení levého posunu |
>>= | přiřazení pravého posunu |
Logické ekvivalenty
Čtyři z bitových operátorů mají ekvivalentní logické operátory. Jsou ekvivalentní v tom, že mají stejné pravdivostní tabulky. Logické operátory však s každým operandem zacházejí jako s jedinou hodnotou, buď true nebo false, spíše než s každým bitem operandu jako s nezávislou hodnotou. Logické operátory považují nulu za nepravdivou a jakoukoli nenulovou hodnotu za pravdivou. Další rozdíl spočívá v tom, že logické operátory fungují vyhodnocení zkratu.
Níže uvedená tabulka odpovídá ekvivalentním operátorům a zobrazuje a a b jako operandy operátorů.
bitový | Logický |
---|---|
a & b | a && b |
a | b | a || b |
a ^ b | a! = b |
~ a | !A |
!=
má stejnou tabulku pravdivosti jako ^
ale na rozdíl od skutečných logických operátorů samo o sobě !=
není striktně řečeno logický operátor. Důvodem je, že logický operátor musí zacházet s jakoukoli nenulovou hodnotou stejně. Používá se jako logický operátor !=
vyžaduje, aby byly operandy nejprve normalizovány. Logické, které se nepoužije na oba operandy, nezmění pravdivostní tabulku, která bude výsledkem, ale zajistí, že všechny nenulové hodnoty budou před porovnáním převedeny na stejnou hodnotu. To funguje, protože !
na nule vždy vede k jedné a !
při jakékoli nenulové hodnotě vždy dojde k nule.
Příklad:
/ * Ekvivalentní bitové a logické testy operátorů * /#zahrnout <stdio.h>prázdnota testOperator(char* název, nepodepsaný char byl, nepodepsaný char očekávaný);int hlavní( prázdnota ){ // - Bitové operátory - // // Pravdivé tabulky zabalené v bitech konst nepodepsaný char operand1 = 0x0A; //0000 1010 konst nepodepsaný char operand2 = 0x0C; //0000 1100 konst nepodepsaný char očekávané = 0x08; //0000 1000 konst nepodepsaný char očekávané nebo = 0x0E; //0000 1110 konst nepodepsaný char expectXor = 0x06; //0000 0110 konst nepodepsaný char operand3 = 0x01; //0000 0001 konst nepodepsaný char očekáváno ne = 0xFE; //1111 1110 testOperator("Bitové AND", operand1 & operand2, Očekávané); testOperator("Bitové NEBO", operand1 | operand2, očekávané nebo); testOperator(„Bitový XOR“, operand1 ^ operand2, expectXor); testOperator(„Bitový NOT“, ~operand3, očekáváno ne); printf(" n"); // - Logické operátory - // konst nepodepsaný char F = 0x00; //Nula konst nepodepsaný char T = 0x01; // Libovolná nenulová hodnota // Tabulky pravdy zabalené do polí konst nepodepsaný char operandArray1[4] = {T, F, T, F}; konst nepodepsaný char operandArray2[4] = {T, T, F, F}; konst nepodepsaný char expectArrayAnd[4] = {T, F, F, F}; konst nepodepsaný char expectArrayOr[4] = {T, T, T, F}; konst nepodepsaný char expectArrayXor[4] = {F, T, T, F}; konst nepodepsaný char operandArray3[2] = {F, T}; konst nepodepsaný char expectArrayNot[2] = {T, F}; int i; pro (i = 0; i < 4; i++) { testOperator(„Logické AND“, operandArray1[i] && operandArray2[i], expectArrayAnd[i]); } printf(" n"); pro (i = 0; i < 4; i++) { testOperator(„Logické NEBO“, operandArray1[i] || operandArray2[i], expectArrayOr[i]); } printf(" n"); pro (i = 0; i < 4; i++) { // Potřebuje! na operandu v případě, že se nenulové hodnoty liší testOperator(„Logický XOR“, !operandArray1[i] != !operandArray2[i], expectArrayXor[i]); } printf(" n"); pro (i = 0; i < 2; i++) { testOperator(„Logické NE“, !operandArray3[i], expectArrayNot[i]); } printf(" n"); vrátit se 0;}prázdnota testOperator( char* název, nepodepsaný char byl, nepodepsaný char očekávaný ){ char* výsledek = (byl == očekávaný) ? "prošel" : „selhalo“; printf("% s% s test, byl:% X očekáván:% X n", název, výsledek, byl, očekávaný); }
Výstupem výše uvedeného programu bude
Bitové AND prošlo, bylo: 8 očekáváno: 8 Bitové OR prošlo, bylo: E očekáváno: E Bitové prošlo XOR, bylo: 6 očekáváno: 6 Bitové prošlo NE, bylo: FE očekáváno: FE Logické AND prošlo, bylo: 1 očekáváno: 1 Logické AND prošlo, bylo: 0 očekáváno: 0 Logické AND prošlo, bylo: 0 očekáváno: 0 Logické AND prošlo, bylo: 0 očekáváno: 0 Logické OR prošlo, bylo: 1 očekáváno: 1 Logické OR prošlo, bylo: 1 očekáváno: 1 Logický OR prošel, byl: 1 očekáván: 1 Logický OR prošel, byl: 0 očekáván: 0 Logický XOR prošel, byl: 0 očekáván: 0 Logický XOR prošel, byl: 1 očekáván: 1 Logický XOR prošel, byl: 1 očekával: 1 Logický XOR prošel, byl: 0 očekáván: 0 Logický NEPŘEDÁNO, byl: 1 Očekáván: 1 Logický NEPRODEJEN, byl: 0 očekáván: 0
Viz také
- Manipulace s bitem
- Bitová operace
- Najít první sadu
- Operátoři v C a C ++
- Bitboard
- Booleova algebra (logika)
- Algoritmus swapu XOR
- Propojený seznam XOR
Reference
- ^ Kernighan; Dennis M. Ritchie (Březen 1988). Programovací jazyk C. (2. vyd.). Englewood Cliffs, NJ: Prentice Hall. ISBN 0-13-110362-8. Archivovány od originál dne 06.07.2019. Citováno 2019-09-07. Mnozí považují za autoritativní odkaz na C.
- ^ A b "Výukové programy - bitové operátory a bitové manipulace v C a C ++". cprogramming.com.
- ^ „Výukový program pro exkluzivní bránu OR“. Základní výukové programy pro elektroniku.
- ^ „Poznámky C ++: Bitové operátory“. fredosaurus.com.
- ^ „3.8 - Bitové operátory“. Naučte se C ++.
- ^ „Operátoři přiřazení C / C ++“. XL C / C ++ V8.0 pro AIX. IBM. Citováno 11. listopadu 2013.