— Привіт, Аміго!

Ще хотів би розповісти про бітові маски та XOR.

Ти вже знаєш, що числа складаються з бітів і над цими бітами можна проводити різні операції. Бітова маска – це коли ми зберігаємо багато різних логічних значень (true/false) як одного цілого числа. У цьому кожному boolean-значенню відповідає певний біт. Ось як це можна робити:

Числа-ступеня двійки (1,2,4,8,16,32,…) займають у двійковому поданні числа лише по одному біту:

Кількість Двійкова вистава
1 0000 0001
2 0000 0010
4 0000 0100
8 0000 1000
16 0001 0000
19 (не ступінь двійки) 0001 0011
31 (не ступінь двійки) 0001 1111

Тому будь-яке ціле число можна розглядати як масив біт або масив boolean.

Ось як можна зберігати різні логічні значення в одному числі:

Значення логічних змінних
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
Упаковка їх в одне число:
int result = 0;
 if (a) result += 1; //1 == 20 - нульовий біт
 if (b) result += 2; //2 == 21 - перший біт
 if(c) result += 4; //4 == 22 - другий біт
 if(d) result += 8; //8 == 23 - третій біт

Тепер кожен біт дорівнює 1, якщо відповідна йому логічна змінна була true.

У нашому випадку true були змінні a і c, значить число result дорівнює 1+4 ==5

0000 0101
0000 dcba

— Начебто зрозуміло, що відбувається.

— Ну, якщо зрозуміло, то пішли далі.

У числі int 32 біти, один з них використовується для знака, а ще 31 можна використовувати для зберігання значень 31 булевської змінної.

— А в числі long 64 біти. Ми там можемо зберігати 63 логічні змінні.

— Ага.

— Півсотні змінних в одному числі. Чимало.

А де таке застосовується?

— Здебільшого там, де треба компактно зберігати багато інформації про об'єкти. Коли зберігаєш багато інформації про об'єкт, завжди набереться кілька десятків логічних змінних. Ось їх зручно зберігати в одному числі.

Саме зберігати. Т.к. користуватися ним у роботі не так вже й зручно.

— До речі, саме хотів запитати. А як нам назад отримати логічні значення їхнього числа?

— Це зовсім не складно. Ось припустимо тобі потрібно дізнатися, чи встановлений 5-й біт числа в одиницю чи ні (2 у п'ятому ступені – це 32). Ось як це можна перевірити:

З'єднуємо числа в одне:
int a = 32; //2 5 == 0010 0000
int b = 8; //23 == 0000 1000
int c = 2; //21 == 0000 0010

int result = a+b+c; //32+8+2 == 42 == 0010 1010
Відновлюємо зворотне значення – перевіряємо, чи встановлено певний біт:
int a = result & 32; // 0010 1010 & 0010 0000 = 0010 0000
int b = result & 8; // 0010 1010 & 0000 1000 = 0000 1000
int c = result & 2; // 0010 1010 & 0000 0010 = 0000 0010

Тобто. фактично, для роботи з бітовими масками потрібні три операції:

1) Встановити певний біт у 0

2) Встановити певний біт в 1

3) Перевірити, яке значення певного біта.

Візьмемо, наприклад, біт номер 6.

Як встановити 1 біт 6?

Код Опис
result = result | 01000000;
result |= 01000000;
Як встановити в 1 біт 6?
result = result & 10111111;
result &= 10111111;
Як встановити 0 біт 6?
з = result & 01000000;
Як отримати значення 6-го біта?

— Дуже незвично, але не складно. Я тепер уже крутий програміст.

— І тепер ще маленька підказка. Як легко отримати числа зі знятим або встановленим певним бітом: 01000000 або 10111111.

Для цього у нас є операції зсуву >> і <<.

Ось 1 – це 2 у нульовому ступені. Тобто. число із встановленим нульовим бітом. Нам треба число із встановленим 6-м бітом.

int c = 1<<6 ; //0000 0001 <<6 == 0100 0000 == 64< /pre>

— Круто! Насправді корисна річ для таких справ.

А якщо мені потрібне число, де всі біти 1, а один певний – 0?

— Це теж не складно:

int d = ~(1<<6)< /span>; //~0100 0000 == 10111111

Тобто. все дуже просто:

Код Опис
result = result | (1<<6);
result |= (1<<6);
Як встановити в 1 біт 6?
result = result & ~(1<<6);
result &=~(1<<6);
Як встановити 0 біт 6?
з = result & (1<<6);
Як отримати значення 6-го біта?

— Виглядає не дуже складно. Але так відразу — не запам'ятаю.

— Зате, якщо зустрінеш десь у чужому коді такий страшний вираз:

«result &=~(1<<6)», знатимеш, що це хтось просто працює з бітовою маскою. А якщо часто зустрічатимеш, то незабаром усе саме запам'ятається.

— Саме запам'ятається… Добре звучить. Дякую за лекцію.