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?
Trả lời
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);
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
@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
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
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
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
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.
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.
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
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. –
bạn có C++ 11 không? và std :: bitset? – dzada
'std :: ios_base :: fmtflags'. –
https://www.google.com/search?q=what+is+a+bitmask – LarryPel