Bạn có thể sử dụng kỹ thuật đóng gói bằng phép nhân giống như được mô tả here. Bằng cách này bạn không cần bất kỳ vòng lặp nào.
Ví dụ với mặt nạ 0b10101001 == 0xA9
như trên và các dữ liệu 8-bit abcdefgh
(với ah là 8 bit), bạn có thể sử dụng các biểu hiện dưới đây để có được 0000aceh
unsigned compress_maskA9(unsigned x)
{
const unsigned mask = 0xA9;
const unsigned mask1 = mask & 0xF0;
const unsigned mask2 = mask & 0x0F;
return (((x & mask1)*0x03000000 >> 28) & 0x0C) | ((x & mask2)*0x50000000 >> 30);
}
Trong trường hợp này có một số chồng chéo của 4 bit khi nhân nên tôi chia chúng thành 2 phần, phần đầu tiên trích bit a và c, sau đó e và h sẽ được trích xuất ở phần sau.
Bạn có thể xem kết quả của nó so với chức năng của Harold live on ideone
Nếu bạn muốn bit của kết quả đảo ngược, bạn có thể dễ dàng thay đổi con số kỳ diệu cho phù hợp.
unsigned compress_maskA9_reversed1(unsigned x)
{
// result: he00 | 00ca;
return (((x & 0x09)*0x88000000 >> 28) & 0x0C) | (((x & 0xA0)*0x04800000) >> 30);
}
hoặc bạn có thể trích xuất các 3 bit e, c và cùng một lúc, để lại h riêng do một số bit chồng chéo:
unsigned compress_maskA9_reversed(unsigned x)
{
return ((x & 0xA8)*0x12400000 >> 29) | (x & 0x01) << 3; // result: 0eca | h000
}
đúng đắn kiểm tra: http://ideone.com/PYUkty
Đối với một số lượng mặt nạ lớn hơn bạn có thể tính toán trước các số ma thuật tương ứng với mặt nạ đó và lưu chúng vào một mảng để sử dụng sau này.
Giải thích
Chúng tôi có abcdefgh & mask1 = a0c00000
........................a0c00000
x 00000011000000000000000000000000 (magic1 = 0x03000000)
__________________________________________________________________
a0c00000........................
+ a0c00000......................... (the leading "a" bit is outside int's range so it'll be truncated
↓↓
__________________________________________________________________
r1 = acc.............................
=> (r1 >> 28) & 0x0C = 0000ac00
Tương tự abcdefgh & mask2 = 0000e00h
........................0000e00h
x 01010000000000000000000000000000 (magic2 = 0x50000000)
__________________________________________________________________
0000e00h............................
+ 0000e00h..............................
↓↓
__________________________________________________________________
r2 = eh..............................
=> (r2 >> 30) = 000000eh
Do đó
((r1 >> 28) & 0x0C) | (r2 >> 30) = 0000aceh
Bạn cần một vòng lặp nếu mặt nạ không phải là hằng số –
Mặt nạ là không đổi nhưng có 512 trong số đó vì vậy .. không thực sự "liên tục". – cen