2010-05-05 8 views
13

No estoy familiarizado con los operadores bit a bit, pero parece que los usé para almacenar configuraciones simples antes.C & PHP: ¿almacenar las configuraciones en un entero usando operadores bit a bit?

Necesito pasar varias opciones con./desc. A una función, y quisiera utilizar un solo número entero para esto. ¿Cómo puedo configurar y leer estas opciones?

+0

No creo que esta sea una respuesta completa, así que lo colocaré como un comentario, pero eche un vistazo a los permisos para archivos y directorios en UNIX como ejemplo. – Clutch

+1

* (relacionado) * http://stackoverflow.com/questions/2131758/bitwise-operations-in-php/2131828#2131828 – Gordon

Respuesta

30

Seguro que puedes hacerlo en PHP.

Digamos que tiene cuatro booleanos que desea almacenar en un solo valor. Eso significa que necesitamos cuatro bits de espacio de almacenamiento

0000 

cada bit, cuando se establece de forma individual, tiene una representación única en decimal

0001 = 1 // or 2^0 
0010 = 2 // or 2^1 
0100 = 4 // or 2^2 
1000 = 8 // or 2^3 

Una forma común de implementar esto es con máscaras de bits para representar cada opción . Los niveles de error de PHP se hacen de esta manera, por ejemplo.

define('OPT_1', 1); 
define('OPT_2', 2); 
define('OPT_3', 4); 
define('OPT_4', 8); 

Entonces, cuando usted tiene un entero que representa 0 o más de estas banderas, que consulte con el operador AND que es &

$options = bindec('0101'); 
// can also be set like this 
// $options = OPT_1 | OPT_3; 

if ($options & OPT_3) 
{ 
    // option 3 is enabled 
} 

Este operador funciona como tal: sólo bits que están set en ambos operadores se encuentran en el resultado

0101 // our options 
0100 // the value of OPT_3 
---- 
0100 // The decimal integer 4 evaluates as "true" in an expression 

Si lo comprobamos contra OPT_2, entonces el resultado sería el siguiente

0101 // our options 
0010 // the value of OPT_2 
---- 
0000 // The decimal integer 0 evaluates as "false" in an expression 
+0

Gracias por romper todo. –

2

cita "La idea no es buena, la verdad. Pasarías mejor pocos booleano. Si desea utilizar bit a bit a continuación

function someFunc($options) 
{ 

    if ($options & 1 != 0) 
     //then option 1 enabled 
    if ($options & (1 << 1) != 0) 
     //then option 2 enabled  
    if ($options & (1 << 2) != 0) 
     //then option 3 enabled  
} 

"

Lo que ha hecho estaría bien si fueras la comprobación de un solo valor, aunque no óptima, lo que la comprobación de que un bit está activado, pero digamos que queríamos ser capaces de adaptarse a cualquier, o exacta que podríamos tener los siguientes métodos

 
function matchExact($in, $match) { // meets your criterion, as would a switch, case, but ultimately not suited for use with flags 
    return $in === $match; 
} 

function matchAny($in, $match) { // meets original criterion with more lexical name however it returns true if any of the flags are true 
    return $in |= $match; 
} 

si luego quería ampliar esto a través de acciones específicas sólo se suceden si el bit x, y, z se selecciona, se puede utilizar la siguiente

 
function matchHas($in, $match) { // more bitwise than === as allows you to conditionally branch upon specific bits being set 
    return $in &= $match; 
} 

También creo que si usted está haciendo lo que se hizo en el arriba, las banderas pueden no ser la mejor idea, los valores exactos pueden ser mejores, lo que tiene el beneficio de permitir acciones más discretas. (0-255) para 8 bits en 8 distintivos distintivos

Toda la razón que las banderas funcionan tan bien es porque en la base 2 "8" no contiene "4", y "2" no contiene "1".

 
________________________ 
|8|4|2|1|Base 10 Value | 
------------------------ 
|1|1|1|1|15   | 
|1|1|1|0|14   | 
|1|1|0|1|13   | 
|1|1|0|0|12   | 
|1|0|1|1|11   | 
|1|0|1|0|10   | 
|1|0|0|1|9    | 
|1|0|0|0|8    | 
|0|1|1|1|7    | 
|0|1|1|0|6    | 
|0|1|0|1|5    | 
|0|1|0|0|4    | 
|0|0|1|1|3    | 
|0|0|1|0|2    | 
|0|0|0|1|1    | 
|0|0|0|0|0    | 
------------------------ 
+2

Los '! = 0''s no son necesarios. –

+0

@Kendall Hopkins "Explícito es mejor que implícito". te dice Zen de Python;) – Andrey

8

Funciona más o menos de la misma manera en ambos idiomas, una comparación lado a lado:

C:

#include <stdio.h> 
#include <stdint.h> 

#define FLAG_ONE 0x0001 
#define FLAG_TWO 0x0002 
#define FLAG_THREE 0x0004 
#define FLAG_FOUR 0x0008 
#define FLAG_ALL (FLAG_ONE|FLAG_TWO|FLAG_THREE|FLAG_FOUR) 

void make_waffles(void) 
{ 
    printf("Yummy! We Love Waffles!!!\n"); 
} 

void do_something(uint32_t flags) 
{ 
    if (flags & FLAG_TWO) 
     make_waffles(); 
} 

int main(void) 
{ 
    uint32_t flags; 

    flags |= FLAG_ALL; 

    /* Lets make some waffles! */ 
    do_something(flags); 

    return 0; 
} 

PHP:

<?php 

define("FLAG_ONE", 0x0001); 
define("FLAG_TWO", 0x0002); 
define("FLAG_THREE", 0x0004); 
define("FLAG_FOUR", 0x0008); 
define("FLAG_ALL", FLAG_ONE|FLAG_TWO|FLAG_THREE|FLAG_FOUR); 

function make_waffles() 
{ 
    echo 'Yummy! We Love Waffles!!!'; 
} 

function do_something($flags) 
{ 
    if ($flags & FLAG_TWO) 
     make_waffles(); 
} 

$flags |= FLAG_TWO; 
do_something($flags); 

?> 

Tenga en cuenta que no necesita usar absolutamente constantes, solo los uso por costumbre. Ambos ejemplos se ejecutarán, compilé la versión C a través del gcc -Wall flags.c -o flags. Cambie flags en cualquier ejemplo a cualquier cosa menos FLAG_TWO o FLAG_ALL y (lamentablemente) no se harán gofres.

En la versión C, no no tiene que hacer cosquillas al preprocesador, podría ser fácilmente una enumeración, etc. - eso es un ejercicio para el lector.

+0

Genial, este ejemplo es muy comprensible. He estado intentando descubrir operadores bit a bit desde hace un tiempo. Gracias por tener el código tanto en PHP como en C, ya que usaré ambos para esto. –

+0

No hay problema. @Peter Bailey brindó la mejor respuesta, me alegra que hayas aceptado la suya. –

+0

Son las dos buenas respuestas. Traté de aceptar ambos, no funcionó. –

Cuestiones relacionadas