"Bună, Amigo!"

„Aș dori să vorbesc și despre bitmasks și XOR”.

„Știți deja că numerele constau din biți și puteți efectua diverse operații pe acești biți. O mască de biți este o reprezentare a mai multor valori logice diferite (valori adevărate/false) ca un singur întreg. În acest caz, fiecare valoare booleană corespunde cu un pic specific. Iată cum se poate face acest lucru:"

„Reprezentarea binară a puterilor a doi (1, 2, 4, 8, 16, 32, ...) implică doar setarea unui bit:”

Număr Reprezentare binară
1 0000 0001
2 0000 0010
4 0000 0100
8 0000 1000
16 0001 0000
19 (nu o putere de doi) 0001 0011
31 (nu o putere de doi) 0001 1111

„Deci, orice număr întreg poate fi tratat ca o matrice de biți sau o matrice de valori booleene.”

„Iată cum puteți stoca diferite valori booleene într-un număr:”

Valori booleene
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
Valori împachetate într-un singur număr:
int result = 0;
 if (a) result += 1; // 1 == 20 — bit 0
 if (b) result += 2; // 2 == 21 — bit 1
 if (c) result += 4; // 4 == 22 — bit 2
 if (d) result += 8; // 8 == 23 — bit 3

„Acum, fiecare bit este 1 dacă variabila booleană corespunzătoare a fost adevărată.”

În cazul nostru, variabilele a și c au fost adevărate, deci rezultatul este egal cu 1+4 == 5

0000 0101
0000 dcba

— Cred că știu ce se întâmplă.

— Ei bine, dacă înțelegi, să mergem mai departe.

„Un int are 32 de biți. Unul dintre ei este folosit pentru semnul numărului, iar ceilalți 31 pot fi folosiți pentru a stoca valorile a 31 de variabile booleene.”

„Un lung are 64 de biți în care putem stoca 63 de variabile booleene.”

"Da."

— Zeci de variabile înghesuite într-un singur număr. Sunt destul de multe.

„Dar unde se aplică asta?”

„În principal, în situațiile în care trebuie să stocați o mulțime de informații despre obiecte. Când stocați o mulțime de informații despre un obiect, există întotdeauna câteva zeci de variabile booleene. „Cu această abordare, toate sunt stocate convenabil într-un singur număr. ."

„Cu accent pe cuvântul „stocat”. Pentru că, de fapt, folosirea numărului nu este atât de convenabilă.”

"Apropo, tocmai asta am vrut să întreb. Cum extragem valoarea booleană din număr?"

"Nu este deloc complicat. Să presupunem că trebuie să determinați dacă bitul 6 este setat la 1 (2 la puterea lui cinci este 32). Am putea verifica astfel:"

Combină numerele într-unul singur:
int a = 32; // 25 == 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
Extrageți valori prin verificarea anumitor biți:
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

„Astfel, lucrul cu măști de biți implică trei operații:”

1)  Setați un anumit bit la 0

2)  Setați un anumit bit la 1

3)  Verificați valoarea bitului specific.

"Ia bitul 6, de exemplu."

"Cum setați bitul 6 la 1?"

Cod Descriere
result = result | 01000000;
result |= 01000000;
Cum setați bitul 6 la 1?
result = result & 10111111;
result &= 10111111;
Cum setați bitul 6 la 0?
c = result & 01000000;
Cum obțineți valoarea bitului 6?

"Este extrem de neobișnuit, dar nu dificil. Omule, acum sunt un programator la îndemână."

„Și încă un mic sfat despre cum să obțineți cu ușurință numere cu un anumit bit setat la 0 sau 1: 01000000 sau 10111111.”

Pentru aceasta, avem  operatorii >> și  << .

"1 este 2 la puterea zero. Cu alte cuvinte, un număr cu bitul 0 setat la 1. Avem nevoie de un număr cu bitul 6 setat."

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

"Mis! Asta e foarte util pentru astfel de cazuri."

"Dar ce se întâmplă dacă am nevoie de un număr în care fiecare bit este setat la 1, cu excepția unui anumit bit este setat la 0?"

„Nici asta nu este dificil:”

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

„Cu alte cuvinte, totul este foarte simplu:”

Cod Descriere
result = result | (1 << 6);
result |= (1 << 6);
Cum setați bitul 6 la 1?
result = result & ~(1 << 6);
result &= ~(1 << 6);
Cum setați bitul 6 la 0?
c = result & (1 << 6);
Cum obțineți valoarea bitului 6?

"Nu pare foarte dificil. Dar nu-mi voi aminti imediat."

„Dar, dacă întâlniți o expresie înfricoșătoare, cum ar fi „rezultat &= ~(1 << 6)” în codul altcuiva, veți ști că această persoană lucrează doar cu o mască de bit.”

„Și dacă îl întâlnești des, atunci își va aminti pentru tine.”

"Amintiți-vă de sine... Asta sună bine. Mulțumesc pentru lecție."