Gli operatori sui bit permettono la valutazione e manipolazione di specifici bit in un valore intero.
Esempio | Nome | Risultato |
---|---|---|
$a & $b |
And | Vengono accesi i bit che sono accesi sia in $a che in $b. |
$a | $b |
Or (inclusive or) | Vengono accesi i bit che sono accesi o in $a oppure in $b. |
$a ^ $b |
Xor (exclusive or) | Vengono accesi i bit che sono accesi in $a o in $b, ma non quelli accesi in entrambe le variabili. |
~ $a |
Not | Vengono accesi i bit che sono spenti in $a, e viceversa |
$a << $b |
Shift left | Sposta verso sinistra i bit di $a per $b volte (ogni passo significa "moltiplica per due") |
$a >> $b |
Shift right | Sposta verso destra i bit di $a per $b volte (ogni passo significa "dividi per due") |
Lo spostamento di bit in PHP è aritmetico. I bit spostati al di fuori delle estremità sono scartati. Gli spostamenti a sinistra inseriscono zeri a destra mentre il bit di segno è scartato sulla sinistra, quindi il segno di un operando non è conservato. Gli spostamenti a destra copiano il bit di segno sulla sinistra, quindi il segno di un operando è conservato.
Utilizzare le parentesi per assicurare la precedenza desiderata. Per esempio, $a & $b == true valuta l'equivalenza e poi l'operatore and; mentre ($a & $b) == true valuta l'operatore and e poi l'equivalenza.
Prestare attenzione alle conversioni tra tipi di dato. Se entrambi gli operandi sono stringhe, l'operatore bit lavorarà sui valori ASCII dei caratter.
L'opzione ini error_reporting di PHP usa valori imappati sui bit,
fornendo quindi una dimostrazione reale dello spegnimento
dei bit. Per mostrare tutti gli errori, eccettuati gli avvisi,
le istruzioni del file php.ini dicono di usare:
E_ALL & ~E_NOTICE
Si prende il valore di E_ALL: 00000000000000000111011111111111 Quindi quello di E_NOTICE... 00000000000000000000000000001000 ... e lo si inverte con ~: 11111111111111111111111111110111 infine, si usa AND (&) pre trovare i bit che sono accesi in entrambi i valori: 00000000000000000111011111110111
Un altro metodo per ottenere questo risultato è usare XOR (^)
per trovare i bit che sono accesi solo in uno dei due operandi:
E_ALL ^ E_NOTICE
error_reporting può essere usata anche per dimostrare come accendere i bit.
Il modo per mostrare solo gli errori e gli errori recuperabili è:
E_ERROR | E_RECOVERABLE_ERROR
Questo processo combina E_ERROR 00000000000000000000000000000001 e 00000000000000000001000000000000 usando l'operatore OR (|) per recuperare i bit accesi in entrambi i valori: 00000000000000000001000000000001
Example #1 Operazioni AND, OR e XOR su interi
<?php
/*
* Ignorare la sezione iniziale,
* server solo a formattare per rendere più leggibile il risultato.
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<<EOH
--------- --------- -- ---------
risultato valore op test
--------- --------- -- ---------
EOH;
/*
* Ecco gli esempi.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo "\n Bitwise AND \n";
foreach ($values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo "\n Bitwise Inclusive OR \n";
foreach ($values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo "\n Bitwise Exclusive OR (XOR) \n";
foreach ($values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>
Il precedente esempio visualizzerà:
--------- --------- -- --------- risultato valore op test --------- --------- -- --------- Bitwise AND ( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101) ( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101) ( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101) ( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101) ( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101) Bitwise Inclusive OR ( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101) ( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101) ( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101) (13 = 1101) = ( 8 = 1000) | ( 5 = 0101) Bitwise Exclusive OR (XOR) ( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101) ( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101) ( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101) (13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)
Example #2 Operazioni XOR su stringhe
<?php
echo 12 ^ 9; // Ritorna '5'
echo "12" ^ "9"; // Ritorna il carattere Backspace (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Ritorna i valori ascii #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Ritorna 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Ritorna 1
// ((int)"2") ^ 3 == 1
?>
Example #3 Spostamento di bit su interi
<?php
/*
* Ecco gli esempi.
*/
echo "\n--- SPOSTAMENTO A DESTRA SU INTERI POSITIVI ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copia del bit di segno inserito a sinistra');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'i bit escono dal lato destro');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'come sopra; non c'è spostamento oltre lo 0');
echo "\n--- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copia del bit di segno inserito a sinistra');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'i bit escono dal lato destro');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'come sopra; non c'è spostamento oltre il -1');
echo "\n--- SPOSTAMENTO A SINISTRA SU INTERI POSITIVI ---\n";
$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'zeri inseriti a destra');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places, 'i bit di segno sono spostati');
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'i bit escono dal lato sinistro');
echo "\n--- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI ---\n";
$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'zeri inseriti a destra');
$val = -4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val << $places;
p($res, $val, '<<', $places);
$val = -4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'i bit escono dal lato sinistro, incluso il bit di segno');
/*
* Ignorare questa sezione finale,
* server solo a formattare per rendere più leggibile il risultato.
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Espressione: %d = %d %s %d\n", $res, $val, $op, $places);
echo " Decimale:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Binario:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " NOTA: $note\n";
}
echo "\n";
}
?>
Risultato del precedente esempio su macchine a 32 bit:
--- SPOSTAMENTO A DESTRA SU INTERI POSITIVI --- Espressione: 2 = 4 >> 1 Decimale: val=4 res=2 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000010 NOTA: copia del bit di segno inserito a sinistra Espressione: 1 = 4 >> 2 Decimale: val=4 res=1 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000001 Espressione: 0 = 4 >> 3 Decimale: val=4 res=0 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTA: i bit escono dal lato destro Espressione: 0 = 4 >> 4 Decimale: val=4 res=0 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTA: come sopra; non c'è spostamento oltre lo 0 --- SPOSTAMENTO A DESTRA SU INTERI NEGATIVI --- Espressione: -2 = -4 >> 1 Decimale: val=-4 res=-2 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111110 NOTA: copia del bit di segno inserito a sinistra Espressione: -1 = -4 >> 2 Decimale: val=-4 res=-1 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111111 NOTA: i bit escono dal lato destro Espressione: -1 = -4 >> 3 Decimale: val=-4 res=-1 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111111 NOTA: come sopra; non c'è spostamento oltre il -1 --- SPOSTAMENTO A SINISTRA SU INTERI POSITIVI --- Espressione: 8 = 4 << 1 Decimale: val=4 res=8 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000001000 NOTA: zeri inseriti a destra Espressione: 1073741824 = 4 << 28 Decimale: val=4 res=1073741824 Binario: val=00000000000000000000000000000100 res=01000000000000000000000000000000 Espressione: -2147483648 = 4 << 29 Decimale: val=4 res=-2147483648 Binario: val=00000000000000000000000000000100 res=10000000000000000000000000000000 NOTA:i bit di segno sono spostati Espressione: 0 = 4 << 30 Decimale: val=4 res=0 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTA: i bit escono dal lato sinistro --- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI --- Espressione: -8 = -4 << 1 Decimale: val=-4 res=-8 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111000 NOTA: zeri inseriti a destra Espressione: -2147483648 = -4 << 29 Decimale: val=-4 res=-2147483648 Binario: val=11111111111111111111111111111100 res=10000000000000000000000000000000 Espressione: 0 = -4 << 30 Decimale: val=-4 res=0 Binario: val=11111111111111111111111111111100 res=00000000000000000000000000000000 NOTA: i bit escono dal lato sinistro, incluso il bit di segno
Risultato del precedente esempio su macchine a 64 bit:
--- SPOSTAMENTO A DESTRA SU INTERI POSITIVI --- Espressione: 2 = 4 >> 1 Decimale: val=4 res=2 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000010 NOTA: copia del bit di segno inserito a sinistra Espressione: 1 = 4 >> 2 Decimale: val=4 res=1 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000001 Espressione: 0 = 4 >> 3 Decimale: val=4 res=0 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit escono dal lato destro Espressione: 0 = 4 >> 4 Decimale: val=4 res=0 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: come sopra; non c'è spostamento oltre lo 0 --- SPOSTAMENTO A DESTRA SU INTERI NEGATIVI --- Espressione: -2 = -4 >> 1 Decimale: val=-4 res=-2 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111110 NOTA: copia del bit di segno inserito a sinistra Espressione: -1 = -4 >> 2 Decimale: val=-4 res=-1 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 NOTA: i bit escono dal lato destro Espressione: -1 = -4 >> 3 Decimale: val=-4 res=-1 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 NOTA: come sopra; non c'è spostamento oltre il -1 --- SPOSTAMENTO A SINISTRA SU INTERI POSITIVI --- Espressione: 8 = 4 << 1 Decimale: val=4 res=8 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000001000 NOTA: zeri inseriti a destra Espressione: 4611686018427387904 = 4 << 60 Decimale: val=4 res=4611686018427387904 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0100000000000000000000000000000000000000000000000000000000000000 Espressione: -9223372036854775808 = 4 << 61 Decimale: val=4 res=-9223372036854775808 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=1000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit di segno sono spostati Espressione: 0 = 4 << 62 Decimale: val=4 res=0 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit escono dal lato sinistro --- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI --- Espressione: -8 = -4 << 1 Decimale: val=-4 res=-8 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111000 NOTA: zeri inseriti a destra Espressione: -9223372036854775808 = -4 << 61 Decimale: val=-4 res=-9223372036854775808 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1000000000000000000000000000000000000000000000000000000000000000 Espressione: 0 = -4 << 62 Decimale: val=-4 res=0 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit escono dal lato sinistro, incluso il bit di segno
Non spostare a destra per più di 32 bit sui sistemi a 32 bit. Non spostare a sinistra nei casi in cui il risultato è un numero più lungo di 32 bit. Utilizzare le funzioni dell'estensione gmp per manipolazioni di bit su numeri più grandi di PHP_INT_MAX.
vedere anche pack(), unpack(), gmp_and(), gmp_or(), gmp_xor(), gmp_testbit(), gmp_clrbit()