Evo jednostavnog primera, kome god sam ovako objasnjavao - shvatio je
imas recimo jedan bajt u kome cuvas neko flagove. Bajt je velicine 8 bitova i da cuvas space (to se nekada puno radilo kada se programiralo, sada niko i ne vodi racuna o tome, zato valjda i moderan softver tako zdere memoriju) ... ti mozes da 8 flagova zapises u 1 bajt umesto za svaki posebno... evo recimo, prakticno u sql:
imate u users tabeli polje:
...
send_newsletter tinyint unsigned not null default 0,
send_offers tinyint unsigned not null default 0,
send_email tinyint unsigned not null default 0,
..
Znaci ako je neko od tih polja 1 onda korisnik "zeli" ako je 0 onda "ne zeli".
I standardna procedura je :
if ($user->send_newsletter > 0) {
// posalji mu newlsetter
} else if ($user->send_offers > 0) {
// posalji mu offer...
i tako dalje...
Medjutim, mozes da koristis samo jedno polje za sva 3 flaga tako sto definises recimo
send_options tinyint unsigned not null default 0;
i refinises recimo MASKE:
define ('SEND_NEWSLETTER', 1); // binarno 00000001, odnosno 2^0
define ('SEND_OFFER', 2); // binarno 00000010, odnosno 2^1
define ('SEND_EMAIL', 4); // binarno 00000100, odnosno 2^2
define ('SEND_NESTO', 8); // binarno 00001000, odnosno 2^3
define ('SEND_DRUGO', 16); // binarno 00010000, odnosno 2^4
i kada pokupis polje `send_options` iz baze, proveravas:
if ($user->options & SEND_NEWSLETTER) {
// posalji mu newlsetter
if ($user->options & SEND_OFFER) {
// posalji mu offer...
if ($user->options & SEND_EMAIL) {
// posalji mu mail...
Na primer, ako je user izabrao da mu se salje offer i email, onda je upisano u polje: 00000110
jer je offer 00000010 a email 00000100, I onda je računica preko OR (bar jedna 1 u oba polja, znači 01, 10, 11)
Kôd:
00000010
00000100
-----------
00000110 - preko OR
^^ - u ova 2 slučaja se pojavljuje bar jedna 1
Kada to što je upisano u polje maskiras sa AND operatorom koji znaci "I JEDNO I DRUGO", za svaku masku pojedinačno dobijas:
Kôd:
00000110
00000010 // SEND_OFFER = 2, binarno 00000010
-----------
00000010 - sto znaci da je vece od nule i znaci da hoce da
^ samo tu je 1 u oba slucaja
E sada, postoje razne operacije, pored AND, znas da postoji NOT, OR, XOR, XNOR
U tvom slucaju se trazi inverzija bitova u polju, znaci sto je bilo 0 da postane 1 i obrnuto. Dakle ako imas broj 4, cija je binarna vrednost: $value = 1000
$invertovani_broj = ~$value
Dobijaš: $invertovani_broj = 0111
Jedino što treba da paziš je sada broj bitova, a ako koristipš int to zavisi od maxint na sistemu, pa treba da ograničiš na neki razuman broj, recimo ako probaš samo ovako bez obzira na broj bitova, dobićeš:
$value = 1000
$inverted_value = 11111111111111111111111111110111;
Što je tačno jer je $value u stvari: 00000000000000000001000 a ne samo 1000 kako bi ti poželeo
jer je int u stvari 4-bajtni broj (4x8 bitova) na 32-bitnim sistemima.
Ako ideš sa left / right shift, nećeš dobiti ono što se traži "ivertovane vrednosti bitova" jer kada uradiš >> (right shift) za broj 00001000 dobijaš:
Kôd:
00001000
> right shift za jedno polje
00000100
^ sada je ovde
a to nije ono što ti treba.
Generalno, ti bi uvek trebao da dobiješ negativan broj ako je unet pozitivan i obrnuto, jer je prvi bit uvek oznaka +- ( 0 = +, 1 = -)