Operatori
PHP Manual

Operatori sui bit

Gli operatori sui bit permettono la valutazione e manipolazione di specifici bit in un valore intero.

Operatori sui bit
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(01248);
$test 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 "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 sopranon 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

Avviso

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()


Operatori
PHP Manual