Побитови операции в PHP (bitwise operations)

За добро или зло PHP е нестриктен език. Просто казано не е необходимо да дефинирате променливите предварително и можете да им присвоявате стойности от различни типове.
Подобно на другите езици за програмиране PHP разползга свградени (т.нар примитивни) типове:

  • boolean;
  • integer;
  • float;
  • string;
  • и още няколко.

Интересен е типа INTEGER. За него PHP заема 4 байта памет(при 32 битовите системи). Това означава, че можем да съхраним 4294967296 числови комбинации. Има обаче нещо, от което страдат всичкии то ече в PHP integer числата са със знак и няма вграден метод за контрол над това. В този случай най-старшия бит се използва за знак (1 -отрицателно,0 – положително). За контраст в C++ можете да указвате дали числото е със знак или без знак, като използвате модификатора UNSIGNED.
Фиксираната големина от 4 байта ни лишава и от по-“дребни” типове, които заемат 1 или 2 байта. Обяснението за мен е, че PHP е WEB насочен и едва ли на някой ще му потрябва такова нещо (много WEB програмисти изобщо не ги знаят тия неща за байтовете 🙂 ). Но в определени ситуации въпросната липса е по-скоро недостатък. Стискам палци това да се промени в следващите версии.

Ето и един практически пример. За него ми трябва 1 байт за съхранение на стойността на променливата, защото числото е по-малко от 255.
Представете си, че един символ – главна буква “А” на латиница. Искате да извършите побитовата операция NOT върху нейния ASCII код. В PHP побитовото NOT се изобразява със символа “~” – без кавичките.

Пояснение: побитовата операция NOT е позната и като инвертиране на битовете. Това означава, че всеки бит от байта, съдържащ числото ще получи противоположна стойност. И понеже в двоичната бройна система възможностите са 0 и 1, то нулите ще станат единици и обратното.

ASCII кода на “A” е 65. Искаме да направим побитово НЕ върху числото 65:

[code lang=”php”]echo ~65[/code]

Резултатът изненадващо е: -66
Правилният отговоробачее 190!

65(10)=0100 0001(2). Товава NOT(0100 0001)=1011 1110(2)=190(10)

Как го смята PHP?

PHP заделя 4 байта т.е. 32 бита за числото 65.
Т.е. 65(10)=00000000 00000000 00000000 01000001(2).
Тогава NOT(00000000 00000000 00000000 01000001)=11111111 11111111 11111111 10111110(2), което някак “интерпретира” като
-66 (най-старшия бит е 1, което е индикация за отрицателно число).

Заобиколният начин за справяне с проблема е:

  1. Извършвате побитовата операция NOT върху числото;
  2. Извършвате побитова операция AND върху резултата от предната операция с маска 0x000000FF;

<?

$a=65;
$b=~$a;
$c=$b & 0x000000FF;

echo “<br>a=”.$a;
echo “<br>b=”.$b;
echo “<br>c=”.$c;

?>

Резултатът вече е (променливата $c):

[code]a=65
b=-66
c=190[/code]

Две отфункциите, които връщат/приемат информацията байт по байтса fread() и fwrite().
Същият похват може да се използва при останалите побитови операции, ако ситуацията го налага.

Питате се къде изобщо се прилага упоменатият по-горе трик? Ами…в много случаи: хеширане и просто кодиране на данни, връзка с Win32 приложения, работа с данни в двоичен вид и т.н. Ако се занимавате само web частта и използвате php за генериране на съдържание и връзка с бази данни надали ще ви се наложи да го използвате. Но не забравяйте, че php не се използва само за това 🙂

Happy Coding 🙂

Допълнителна информация:

Leave a Reply

Your email address will not be published. Required fields are marked *