2013-09-03 15 views
36

Jak używać go w C++? kiedy jest to przydatne?
Podaj przykład problemu, w którym używana jest maska ​​bitowa, jak to działa. Dzięki!Jak korzystać z maski bitowej?

+2

czy masz C++ 11? i std :: bitset? – dzada

+0

'std :: ios_base :: fmtflags'. –

+4

https://www.google.com/search?q=what+jest+maska_bitowa – LarryPel

Odpowiedz

19

Maskowanie bitów jest "użyteczne" do użycia, gdy chcesz przechowywać (a następnie wyodrębniać) różne dane w ramach pojedynczej wartości danych.

Przykładowa aplikacja, z której korzystałem wcześniej, to wyobrażenie, że przechowujesz kolorowe wartości RGB w 16-bitowej wartości. Więc coś, co wygląda tak:

RRRR RGGG GGGB BBBB 

Następnie można użyć nieco maskowania pobrać składowych koloru w następujący sposób:

const unsigned short redMask = 0xF800; 
    const unsigned short greenMask = 0x07E0; 
    const unsigned short blueMask = 0x001F; 

    unsigned short lightGray = 0x7BEF; 

    unsigned short redComponent = (lightGray & redMask) >> 11; 
    unsigned short greenComponent = (lightGray & greenMask) >> 5; 
    unsigned short blueComponent = (lightGray & blueMask); 
+1

Nie rozumiem tego, mówisz, że 0xF800 to po prostu grupa bitów, które wybiera z (aka wyodrębnia te bity z ustawionej grupy bajtów według adresu)? Myślałem, że maska ​​bitowa jest w zasadzie intem o tej samej wielkości co dane (w tym przypadku będzie to 48 bitów) i maska ​​zostanie nałożona na wierzch, gdy wartości maski wynoszą 1, wartość wyświetlanego przez nią bitu, a kiedy jest zero, nie pozwala, zignorować off bitów? i na co się przesuwa? – MarcusJ

+0

@MarcusJ: zapoznaj się z przykładem za pomocą programu goGud poniżej, który zawiera więcej szczegółów na temat masek bitowych (np. Http://stackoverflow.com/questions/18591924/how-to-use-bitmask/18592049#18592049) – a505999

+0

Jestem idiota. Wiedziałem, czym jest bitmasking, ale nie zdawałem sobie sprawy, że potrójny RGB nie ma 8 bitów, co powoduje moje zamieszanie. dzięki za pomoc! :) – MarcusJ

93

Krótko maski bitowej pomaga manipulować pozycję wielu wartości. Tutaj jest dobry przykład;

Bitflagi są metodą przechowywania wielu wartości, które nie wykluczają się wzajemnie, w jednej zmiennej. Prawdopodobnie już je widziałeś. Każda flaga jest pozycją bitową, którą można włączać i wyłączać. Trzeba wówczas kilka bitmasks #defined dla każdej pozycji bitowej, dzięki czemu można łatwo manipulować go:

#define LOG_ERRORS   1 // 2^0, bit 0 
    #define LOG_WARNINGS   2 // 2^1, bit 1 
    #define LOG_NOTICES   4 // 2^2, bit 2 
    #define LOG_INCOMING   8 // 2^3, bit 3 
    #define LOG_OUTGOING   16 // 2^4, bit 4 
    #define LOG_LOOPBACK   32 // and so on... 

// Only 6 flags/bits used, so a char is fine 
unsigned char flags; 

// initialising the flags 
// note that assignming a value will clobber any other flags, so you 
// should generally only use the = operator when initialising vars. 
flags = LOG_ERRORS; 
// sets to 1 i.e. bit 0 

//initialising to multiple values with OR (|) 
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING; 
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3 

// setting one flag on, leaving the rest untouched 
// OR bitmask with the current value 
flags |= LOG_INCOMING; 

// testing for a flag 
// AND with the bitmask before testing with == 
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) 
    ... 

// testing for multiple flags 
// as above, OR the bitmasks 
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) 
     == (LOG_INCOMING | LOG_OUTGOING)) 
    ... 

// removing a flag, leaving the rest untouched 
// AND with the inverse (NOT) of the bitmask 
flags &= ~LOG_OUTGOING; 

// toggling a flag, leaving the rest untouched 
flags ^= LOG_LOOPBACK; 



** 

UWAGA: NIE używać operator równości (tj bitflags == maska ​​bitowa) do badania, jeśli flagą jest ustawione - to wyrażenie będzie prawdziwe tylko wtedy, gdy ustawiona zostanie flaga, a wszystkie pozostałe zostaną rozbrojone. Aby przetestować dla pojedynczej flagi trzeba użyć & i ==:

**

if (flags == LOG_WARNINGS) //DON'T DO THIS 
    ... 
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) // The right way 
    ... 
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) // Test for multiple flags set 
     == (LOG_INCOMING | LOG_OUTGOING)) 
    ... 

Można również wyszukiwać C++ Triks

+0

w twoim przykładzie dotyczącym bitflagów, skąd wiadomo, który bit należy do której zmiennej? to jest pozycja w bajcie, czy rzeczywista wartość bajtu włącza się i wyłącza niektóre funkcje? – MarcusJ

3

Załóżmy, że mam 32-bitową wartość ARGB z 8-bitów na kanał. I chce wymienić składnik alfa z inną wartość alfa, jak 0x45

unsigned long alpha = 0x45 
unsigned long pixel = 0x12345678; 
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24)); 

Maska obraca top 8 bitów 0, gdzie stara wartość alfa. Wartość alfa przesuwa się do ostatecznych pozycji bitów, które zajmie, a następnie zmieni OR-ed w wartość maskowanego piksela. Ostateczny wynik to 0x45345678, który jest przechowywany w pikselach.

3

Maski bitowe są używane, gdy chcesz kodować wiele warstw informacji w jednym numerze.

Tak (przy założeniu, że uprawnienia pliku Unix), jeśli chcesz przechowywać 3 poziomy ograniczeń dostępu (odczyt, zapis, wykonanie), możesz sprawdzić dla każdego poziomu, zaznaczając odpowiedni bit.

rwx 
--- 
110 

110 w bazie przekłada 2 do 6 w bazie 10.

Więc można łatwo sprawdzić, czy ktoś może na przykład odczytaj plik przy pomocy pola zgody z wymaganym zezwoleniem.

Pseudokod:

PERM_READ = 4 
PERM_WRITE = 2 
PERM_EXEC = 1 

user_permissions = 6 

if (user_permissions & PERM_READ == TRUE) then 
    // this will be reached, as 6 & 4 is true 
fi 

Musisz rozumienie roboczą binarnej reprezentacji liczb i operatorów logicznych zrozumieć pól bitowych.

+0

Dlaczego jednak 6 i 4 jest prawdziwe? jaka operacja matematyczna rzeczywiście tu się dzieje? – MarcusJ

+1

Liczba binarna to 0 lub 1. 4 to "100", 6 to "110". Do _i_ liczb, _i_ każda cyfra binarna. –