Operadores bit a bit

Los operadores bit a bit permiten la evaluación y la manipulación de bits específicos dentro de un integer.

Operadores bit a bit
EjemploNombreResultado
$a & $bAnd (y)Los bits que están activos en ambos $a y $b son activados.
$a | $bOr (o inclusivo)Los bits que están activos ya sea en $a o en $b son activados.
$a ^ $bXor (o exclusivo) Los bits que están activos en $a o en $b, pero no en ambos, son activados.
~ $aNot (no) Los bits que están activos en $a son desactivados, y viceversa.
$a << $bShift left(desplazamiento a izquierda) Desplaza los bits de $a, $b pasos a la izquierda (cada paso quiere decir "multiplicar por dos").
$a >> $bShift right (desplazamiento a derecha) Desplaza los bits de $a, $b pasos a la derecha (cada paso quiere decir "dividir por dos").

El desplazamiento de bits en PHP es aritmético. Los bits desplazados por fuera de cualquiera de los extremos son descartados. Desplazamientos de izquierda tienen ceros desplazados a la derecha mientras que el bit de signo es desplazado fuera a la izquierda, es decir que no se conserva el signo de un operando. Desplazamientos a la derecha tienen copias del bit de signo desplazado a la izquierda, es decir que se conserva el signo de un operando.

Utilice paréntesis para garantizar la precedencia deseada. Por ejemplo, $a & $b == true evalúa la equivalencia y luego el bit a bit, mientras que ($a & $b) == true evalúa el bit a bit y luego la equivalencia.

Si los operandos para los operadores &, | y ^ son string, la operación se realizará con los valores ASCII de los caracteres que componen dichos string, y el resultado será también un string. En todos los demás casos, ambos operandos serán convertidos a valores de tipo integer y el resultado será también un integer.

Si el operando del operados ~ es un string, la operación se realizará con valores los ASCII de los caracteres que componen dicho string, y el resultado también será un string; en caso contrario, el operando y el resultado serán tratados como valores de tipo integer.

Ambos operandos y el resultado de lo operadores << y >> siempre son tratados como valores de tipo integer.

 El ajuste ini error_reporting utiliza valores a nivel de bit, lo que ofrece una demostración del mundo real de desactivar bits. Para mostrar todos los errores, a excepción de los avisos, las instrucciones del archivo php.ini dicen utilizar: E_ALL & ~E_NOTICE

 Esto funciona iniciando con E_ALL: 00000000000000000111011111111111 Luego se toma el valor de E_NOTICE ... 00000000000000000000000000001000 ... y se invierte por medio de ~: 11111111111111111111111111110111 Finalmente, se utiliza AND (&) para encontrar los bits que se activaron en ambos valores: 00000000000000000111011111110111

 Otra forma de lograrlo es mediante XOR (^) para encontrar los bits que están activados en sólo el primer valor o en el otro: E_ALL ^ E_NOTICE

 error_reporting también se puede utilizar para demostrar la activación de bits. La forma para mostrar sólo los errores y los errores recuperables es: E_ERROR | E_RECOVERABLE_ERROR

 Este proceso combina E_ERROR 00000000000000000000000000000001 y 00000000000000000001000000000000 usando el operador OR (|) para obtener los bits activados en cualquiera de estos valores: 00000000000000000001000000000001

Ejemplo #1 Operaciones AND, OR y XOR bit a bit sobre integers

<?php


$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";

echo <<<EOH
--------- --------- -- ---------
resultado valor op prueba
--------- --------- -- ---------
EOH;




$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;

echo
"\n AND bit a bit \n";
foreach (
$values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}

echo
"\n OR inclusivo bit a bit \n";
foreach (
$values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}

echo
"\n OR exclusivo (XOR) bit a bit \n";
foreach (
$values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>

El resultado del ejemplo sería:

 --------- --------- -- --------- resultado valor op prueba --------- --------- -- --------- AND bit a bit ( 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) OR inclusivo bit a bit ( 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) OR exclusivo (XOR) bit a bit ( 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) 

Ejemplo #2 Operaciones XOR bit a bit sobre strings

<?php
echo 12 ^ 9; // Sale '5'

echo "12" ^ "9"; // Sale el caracter de retroceso (ascii 8)

Ejemplo #3 Desplazamiento de bits sobre integers

<?php


echo "\n--- DESPLAZAMIENTO DE BITS A LA DERECHA SOBRE ENTEROS POSITIVOS ---\n";

$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copia del bit de signo desplazado hacia el lado izquierdo');

$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);

$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits desplazados fuera del lado derecho');

$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'mismo resultado que arriba; no se puede desplazar más allá del 0');


echo
"\n--- DESPLAZAMIENTO DE BITS A LA DERECHA SOBRE ENTEROS NEGATIVOS ---\n";

$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copia del bit de signo desplazado al lado izquierdo');

$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits desplazados fuera del lado derecho');

$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'mismo resultado que arriba; no se puede desplazar más allá del -1');


echo
"\n--- DESPLAZAMIENTO DE BITS A LA IZQUIERDA SOBRE ENTEROS POSITIVOS ---\n";

$val = 4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'ceros rellenan en el lado derecho');

$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, 'bit de signo resulta desplazado fuera');

$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val << $places;
p($res, $val, '<<', $places, 'bit de signo desplazado fuera del lado izquierdo');


echo
"\n--- DESPLAZAMIENTO DE BITS A LA IZQUIERDA SOBRE ENTEROS NEGATIVOS ---\n";

$val = -4;
$places = 1;
$res = $val << $places;
p($res, $val, '<<', $places, 'ceros rellenan en el lado derecho');

$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, 'bits desplazados fuera del lado izquierdo, incluyendo el bit de signo');




function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";

printf("Expression: %d = %d %s %d\n", $res, $val, $op, $places);

echo
" Decimal:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);

echo
" Binary:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);

if (
$note) {
echo
" NOTE: $note\n";
}

echo
"\n";
}
?>

El resultado del ejemplo en equipos de 32 bit sería:

 --- DESPLAZAMIENTO DE BITS A LA DERECHA SOBRE ENTEROS POSITIVOS --- Expression: 2 = 4 >> 1 Decimal: val=4 res=2 Binary: val=00000000000000000000000000000100 res=00000000000000000000000000000010 NOTE: copia del bit de signo desplazado hacia el lado izquierdo Expression: 1 = 4 >> 2 Decimal: val=4 res=1 Binary: val=00000000000000000000000000000100 res=00000000000000000000000000000001 Expression: 0 = 4 >> 3 Decimal: val=4 res=0 Binary: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTE: bits desplazados fuera del lado derecho Expression: 0 = 4 >> 4 Decimal: val=4 res=0 Binary: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTE: mismo resultado que arriba; no se puede desplazar más allá del 0 --- DESPLAZAMIENTO DE BITS A LA DERECHA SOBRE ENTEROS NEGATIVOS --- Expression: -2 = -4 >> 1 Decimal: val=-4 res=-2 Binary: val=11111111111111111111111111111100 res=11111111111111111111111111111110 NOTE: copia del bit de signo desplazado al lado izquierdo Expression: -1 = -4 >> 2 Decimal: val=-4 res=-1 Binary: val=11111111111111111111111111111100 res=11111111111111111111111111111111 NOTE: bits desplazados fuera del lado derecho Expression: -1 = -4 >> 3 Decimal: val=-4 res=-1 Binary: val=11111111111111111111111111111100 res=11111111111111111111111111111111 NOTE: mismo resultado que arriba; no se puede desplazar más allá del -1 --- DESPLAZAMIENTO DE BITS A LA IZQUIERDA SOBRE ENTEROS POSITIVOS --- Expression: 8 = 4 << 1 Decimal: val=4 res=8 Binary: val=00000000000000000000000000000100 res=00000000000000000000000000001000 NOTE: ceros rellenan en el lado derecho Expression: 1073741824 = 4 << 28 Decimal: val=4 res=1073741824 Binary: val=00000000000000000000000000000100 res=01000000000000000000000000000000 Expression: -2147483648 = 4 << 29 Decimal: val=4 res=-2147483648 Binary: val=00000000000000000000000000000100 res=10000000000000000000000000000000 NOTE: bit de signo resulta desplazado fuera Expression: 0 = 4 << 30 Decimal: val=4 res=0 Binary: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTE: bit de signo desplazado fuera del lado izquierdo --- DESPLAZAMIENTO DE BITS A LA IZQUIERDA SOBRE ENTEROS NEGATIVOS --- Expression: -8 = -4 << 1 Decimal: val=-4 res=-8 Binary: val=11111111111111111111111111111100 res=11111111111111111111111111111000 NOTE: ceros rellenan en el lado derecho Expression: -2147483648 = -4 << 29 Decimal: val=-4 res=-2147483648 Binary: val=11111111111111111111111111111100 res=10000000000000000000000000000000 Expression: 0 = -4 << 30 Decimal: val=-4 res=0 Binary: val=11111111111111111111111111111100 res=00000000000000000000000000000000 NOTE: bits desplazados fuera del lado izquierdo, incluyendo el bit de signo 

El resultado del ejemplo en equipos de 64 bit sería:

 --- DESPLAZAMIENTO DE BITS A LA DERECHA SOBRE ENTEROS POSITIVOS --- Expression: 2 = 4 >> 1 Decimal: val=4 res=2 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000010 NOTE: copia del bit de signo desplazado hacia el lado izquierdo Expression: 1 = 4 >> 2 Decimal: val=4 res=1 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000001 Expression: 0 = 4 >> 3 Decimal: val=4 res=0 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTE: bits desplazados fuera del lado derecho Expression: 0 = 4 >> 4 Decimal: val=4 res=0 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTE: mismo resultado que arriba; no se puede desplazar más allá del 0 --- DESPLAZAMIENTO DE BITS A LA DERECHA SOBRE ENTEROS NEGATIVOS --- Expression: -2 = -4 >> 1 Decimal: val=-4 res=-2 Binary: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111110 NOTE: copia del bit de signo desplazado al lado izquierdo Expression: -1 = -4 >> 2 Decimal: val=-4 res=-1 Binary: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 NOTE: bits desplazados fuera del lado derecho Expression: -1 = -4 >> 3 Decimal: val=-4 res=-1 Binary: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 NOTE: mismo resultado que arriba; no se puede desplazar más allá del -1 --- DESPLAZAMIENTO DE BITS A LA IZQUIERDA SOBRE ENTEROS POSITIVOS --- Expression: 8 = 4 << 1 Decimal: val=4 res=8 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000001000 NOTE: ceros rellenan en el lado derecho Expression: 4611686018427387904 = 4 << 60 Decimal: val=4 res=4611686018427387904 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0100000000000000000000000000000000000000000000000000000000000000 Expression: -9223372036854775808 = 4 << 61 Decimal: val=4 res=-9223372036854775808 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=1000000000000000000000000000000000000000000000000000000000000000 NOTE: bit de signo resulta desplazado fuera Expression: 0 = 4 << 62 Decimal: val=4 res=0 Binary: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTE: bit de signo desplazado fuera del lado izquierdo --- DESPLAZAMIENTO DE BITS A LA IZQUIERDA SOBRE ENTEROS NEGATIVOS --- Expression: -8 = -4 << 1 Decimal: val=-4 res=-8 Binary: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111000 NOTE: ceros rellenan en el lado derecho Expression: -9223372036854775808 = -4 << 61 Decimal: val=-4 res=-9223372036854775808 Binary: val=1111111111111111111111111111111111111111111111111111111111111100 res=1000000000000000000000000000000000000000000000000000000000000000 Expression: 0 = -4 << 62 Decimal: val=-4 res=0 Binary: val=1111111111111111111111111111111111111111111111111111111111111100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTE: bits desplazados fuera del lado izquierdo, incluyendo el bit de signo 
Advertencia

Desplazar un integer por valores mayores o iguales al ancho del tipo long integer del sistema resultará en un comportamiento indefinido. En otras palabras, no desplace más de 31 bit en sistemas de 32 bit, y no desplace más de 63 bit en sistemas de 64 bit.

Use funciones de la extensión gmp para manipular a nivel de bit números mayores que PHP_INT_MAX.

Ver también pack(), unpack(), gmp_and(), gmp_or(), gmp_xor(), gmp_testbit(), gmp_clrbit()

To Top