Я досить новачок у програмуванні на С, і мені траплялося бітове маскування. Чи може хтось пояснити мені загальну концепцію та функцію біт-маскування? Приклади високо цінуються.
Я досить новачок у програмуванні на С, і мені траплялося бітове маскування. Чи може хтось пояснити мені загальну концепцію та функцію біт-маскування? Приклади високо цінуються.
Відповіді:
Маска визначає, які біти потрібно зберегти та які біти потрібно очистити.
Маскування - це акт нанесення маски на значення. Це здійснюється завдяки:
Нижче наведено приклад вилучення підмножини бітів у значенні:
Mask: 00001111b
Value: 01010101b
Застосування маски до значення означає, що ми хочемо очистити перший (вищий) 4 біт, а останній (нижній) 4 біт. Таким чином ми витягли нижні 4 біти. Результат:
Mask: 00001111b
Value: 01010101b
Result: 00000101b
Маскування реалізується за допомогою AND, тому в C ми отримуємо:
uint8_t stuff(...) {
uint8_t mask = 0x0f; // 00001111b
uint8_t value = 0x55; // 01010101b
return mask & value;
}
Ось досить поширений випадок використання: Вилучення окремих байтів із більшого слова. Ми визначаємо біти високого порядку в слові як перший байт. Для цього ми використовуємо два оператори &
, і >>
(зсув праворуч). Ось як можна дістати чотири байти з 32-бітного цілого числа:
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
...
}
Зауважте, що ви можете змінити порядок операторів вище, ви можете спершу зробити маску, а потім зсув. Результати однакові, але тепер вам доведеться використовувати іншу маску:
uint32_t byte3 = (value & 0xff00) >> 8;
&
.
#define MASK 0x000000FF .... my_uint32_t &= ~MASK
.
b
вказати двійковий літерал не підтримує всіма компіляторами, правильно?
Маскування означає зберігати / змінювати / видаляти бажану частину інформації. Подивимось операцію маскування зображень; як - ця маскувальна операція видаляє будь-яку річ, яка не є шкірою-
Ми робимо І операцію в цьому прикладі. Є й інші оператори маскування - АБО , XOR .
Біт-маскування означає накладення маски на біти. Ось трохи маскування з 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
залишаються лише середні 4 біти (оскільки ці біти є в цій масці).
Давайте побачимо це за допомогою 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]
Тепер середні 4 біти перевернуті ( 1
стали 0
, 0
стали 1
).
Отже, використовуючи біт-маску, ми можемо отримати доступ до окремих бітів [ приклади ]. Іноді цей прийом може бути використаний і для підвищення продуктивності. Візьмемо це для прикладу-
bool isOdd(int i) {
return i%2;
}
Ця функція повідомляє, чи ціле число непарне / парне. Ми можемо досягти того ж результату за рахунок більшої ефективності, використовуючи біт-маску-
bool isOdd(int i) {
return i&1;
}
Коротке пояснення : якщо найменший значущий біт двійкового числа, 1
то він непарний; бо 0
воно буде рівним. Таким чином, роблячи і з 1
ми видаляємо всі інші біти для найменшого значущого біта тобто за винятком:
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]