2013-09-03 24 views
36

Làm cách nào để sử dụng nó trong C++? khi nào là hữu ích khi sử dụng?
Vui lòng cho tôi ví dụ về sự cố trong đó bitmap được sử dụng, cách hoạt động của nó. Cảm ơn!Làm thế nào để sử dụng bitmask?

+2

bạn có C++ 11 không? và std :: bitset? – dzada

+0

'std :: ios_base :: fmtflags'. –

+4

https://www.google.com/search?q=what+is+a+bitmask – LarryPel

Trả lời

19

Mặt nạ bit là "hữu ích" để sử dụng khi bạn muốn lưu trữ (và sau đó trích xuất) dữ liệu khác nhau trong một giá trị dữ liệu duy nhất.

Ứng dụng ví dụ mà tôi đã sử dụng trước đây là hình dung bạn đã lưu trữ các giá trị RGB màu trong giá trị 16 bit. Vì vậy, cái gì đó trông như thế này:

RRRR RGGG GGGB BBBB 

Sau đó, bạn có thể sử dụng mặt nạ chút để lấy các thành phần màu sắc như sau:

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

Tôi không hiểu điều này, bạn đang nói 0xF800 về cơ bản là một nhóm bit mà nó chọn (aka nó trích xuất các bit từ một nhóm các byte theo địa chỉ)? Tôi nghĩ rằng một bitmask cơ bản là một int có cùng kích thước với dữ liệu (vì vậy trong trường hợp này nó sẽ là 48 bit) và mặt nạ được áp dụng overtop, khi các giá trị của mặt nạ là 1 giá trị của bit cơ bản hiển thị, và khi nó bằng không, nó không, cho phép bạn bỏ qua các bit off? và dịch chuyển là gì? – MarcusJ

+0

@MarcusJ: vui lòng tham khảo ví dụ của goGud bên dưới, cung cấp thêm chi tiết về bitmask (ví dụ: http://stackoverflow.com/questions/18591924/how-to-use-bitmask/18592049#18592049) – a505999

+0

Tôi là một kẻ ngốc. Tôi biết bitmasking là gì, nhưng tôi đã không nhận ra rằng RGB ba không phải là 8 bit mỗi, gây nhầm lẫn của tôi. cảm ơn sự giúp đỡ của bạn! :) – MarcusJ

93

ngắn gọn bitmask giúp thao tác vị trí của nhiều giá trị. Có một ví dụ điển hình ở đây;

Bitflags là phương pháp lưu trữ nhiều giá trị, không độc quyền, trong một biến. Bạn đã có thể nhìn thấy chúng trước đây. Mỗi cờ là một vị trí bit có thể được bật hoặc tắt. Sau đó bạn có một loạt các bitmasks #defined cho mỗi vị trí bit, do đó bạn có thể dễ dàng thao tác nó:

#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; 



** 

CẢNH BÁO: KHÔNG sử dụng các nhà điều hành bình đẳng (tức bitflags == bitmask) để thử nghiệm nếu một lá cờ được đặt - biểu thức đó sẽ chỉ đúng nếu cờ đó được đặt và tất cả các cờ khác sẽ không được đặt. Để kiểm tra cho một lá cờ đơn bạn cần phải sử dụng & và ==:

**

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)) 
    ... 

Bạn cũng có thể tìm kiếm C++ Triks

+0

trong ví dụ của bạn về bitflags, làm cách nào để biết bit nào thuộc về biến nào? đó là vị trí trong byte, hoặc giá trị thực tế của byte bật và tắt các tính năng nhất định? – MarcusJ

3

Hãy nói rằng tôi có giá trị ARGB 32-bit với 8 bit cho mỗi kênh. Tôi muốn thay thế thành phần alpha bằng một giá trị alpha khác, chẳng hạn như 0x45

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

Mặt nạ biến 8 bit đầu thành 0, trong đó giá trị alpha cũ là. Giá trị alpha được chuyển lên tới vị trí bit cuối cùng mà nó sẽ lấy, sau đó là OR-ed vào giá trị pixel được che dấu. Kết quả cuối cùng là 0x45345678 được lưu trữ thành pixel.

3

Bitmask được sử dụng khi bạn muốn mã hóa nhiều lớp thông tin trong một số duy nhất.

Vì vậy, (giả sử quyền truy cập tệp unix) nếu bạn muốn lưu trữ 3 cấp giới hạn truy cập (đọc, ghi, thực thi), bạn có thể kiểm tra từng cấp bằng cách kiểm tra bit tương ứng.

rwx 
--- 
110 

110 tại cơ sở 2 dịch đến 6 trong cơ sở 10

Vì vậy, bạn có thể dễ dàng kiểm tra xem một người nào đó được phép ví dụ đọc tệp bằng cách và cho phép trường có quyền mong muốn.

Mã giả:

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 

Bạn cần một sự hiểu biết làm việc của đại diện nhị phân của số và toán tử logic để hiểu lĩnh vực bit.

+0

Tại sao 6 & 4 là true? những gì hoạt động toán học thực sự xảy ra ở đây? – MarcusJ

+1

Một số nhị phân là 0 hoặc 1. 4 là '100', 6 là' 110'. Để _and_ các số, _and_ mỗi số nhị phân. –