Jestem całkiem nowy w programowaniu w C i napotkałem maskowanie bitów. Czy ktoś może mi wyjaśnić ogólną koncepcję i funkcję maskowania bitów? Przykłady są bardzo cenione.
Jestem całkiem nowy w programowaniu w C i napotkałem maskowanie bitów. Czy ktoś może mi wyjaśnić ogólną koncepcję i funkcję maskowania bitów? Przykłady są bardzo cenione.
Odpowiedzi:
Maska określa, które bity chcesz zachować, a które bity chcesz wyczyścić.
Maskowanie to czynność nakładania maski na wartość. Dokonuje się tego poprzez:
Poniżej znajduje się przykład wyodrębnienia podzbioru bitów z wartości:
Mask: 00001111b
Value: 01010101b
Zastosowanie maski do wartości oznacza, że chcemy wyczyścić pierwsze (wyższe) 4 bity i zachować ostatnie (niższe) 4 bity. W ten sposób wyodrębniliśmy dolne 4 bity. Wynik to:
Mask: 00001111b
Value: 01010101b
Result: 00000101b
Maskowanie jest realizowane za pomocą AND, więc w C otrzymujemy:
uint8_t stuff(...) {
uint8_t mask = 0x0f; // 00001111b
uint8_t value = 0x55; // 01010101b
return mask & value;
}
Oto dość powszechny przypadek użycia: Wyodrębnianie pojedynczych bajtów z większego słowa. Definiujemy bity wysokiego rzędu w słowie jako pierwszy bajt. Używamy do tego dwóch operatorów &
i >>
(przesuń w prawo). W ten sposób możemy wyodrębnić cztery bajty z 32-bitowej liczby całkowitej:
void more_stuff(uint32_t value) { // Example value: 0x01020304
uint32_t byte1 = (value >> 24); // 0x01020304 >> 24 is 0x01 so
// no masking is necessary
uint32_t byte2 = (value >> 16) & 0xff; // 0x01020304 >> 16 is 0x0102 so
// we must mask to get 0x02
uint32_t byte3 = (value >> 8) & 0xff; // 0x01020304 >> 8 is 0x010203 so
// we must mask to get 0x03
uint32_t byte4 = value & 0xff; // here we only mask, no shifting
// is necessary
...
}
Zauważ, że możesz zmienić kolejność operatorów powyżej, możesz najpierw zrobić maskę, a potem przesunięcie. Wyniki są takie same, ale teraz musiałbyś użyć innej maski:
uint32_t byte3 = (value & 0xff00) >> 8;
&
.
#define MASK 0x000000FF .... my_uint32_t &= ~MASK
.
b
dosłowne wskazać binarny nie jest obsługiwana przez wszystkie kompilatory, prawda?
Maskowanie oznacza zachowanie / zmianę / usunięcie żądanej części informacji. Pozwala zobaczyć operację maskowania obrazu; jak - ta operacja maskowania usuwa wszystko, co nie jest skórką -
W tym przykładzie wykonujemy operację AND . Istnieją również inne operatory maskowania - OR , XOR .
Maskowanie bitów oznacza nakładanie maski na bity. Oto maskowanie bitów za pomocą AND -
1 1 1 0 1 1 0 1 [input] (&) 0 0 1 1 1 1 0 0 [mask] ------------------------------ 0 0 1 0 1 1 0 0 [output]
1
Pozostają więc tylko 4 środkowe bity (ponieważ te bity są w tej masce).
Zobaczmy to dzięki XOR -
1 1 1 0 1 1 0 1 [input] (^) 0 0 1 1 1 1 0 0 [mask] ------------------------------ 1 1 0 1 0 0 0 1 [output]
Teraz środkowe 4 bity są odwrócone ( 1
stały się 0
, 0
stały się 1
).
Tak więc za pomocą maski bitowej możemy uzyskać dostęp do poszczególnych bitów [ przykłady ]. Czasami tę technikę można również wykorzystać do poprawy wydajności. Weź to na przykład
bool isOdd(int i) {
return i%2;
}
Ta funkcja informuje, czy liczba całkowita jest nieparzysta / parzysta. Możemy osiągnąć ten sam wynik z większą wydajnością za pomocą maski bitowej
bool isOdd(int i) {
return i&1;
}
Krótkie wyjaśnienie : Jeżeli najmniej znaczący bit liczby binarnej 1
jest nieparzysty; bo 0
tak będzie. Tak, wykonując I z 1
usuwamy wszystkie inne kawałki z wyjątkiem najmniej znaczącego bitu tzn:
55 -> 0 0 1 1 0 1 1 1 [input] (&) 1 -> 0 0 0 0 0 0 0 1 [mask] --------------------------------------- 1 <- 0 0 0 0 0 0 0 1 [output]