2010-05-05 5 views
13

Je ne suis pas familier avec les opérateurs au niveau du bit, mais j'ai l'impression qu'ils sont utilisés pour stocker des paramètres simples avant.C & PHP: Stocker les paramètres dans un entier à l'aide d'opérateurs au niveau du bit?

Je dois passer plusieurs options d'activation/désactivation à une fonction, et j'aimerais utiliser un seul entier pour cela. Comment puis-je configurer et lire ces options?

+0

Je ne pense pas que ce soit une réponse complète donc je vais le placer comme un commentaire, mais jetez un oeil sur les autorisations pour les fichiers et les répertoires sur UNIX comme exemple. – Clutch

+1

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

Répondre

30

Vous pouvez le faire en PHP.

Imaginons que vous ayez quatre booléens à stocker dans une seule valeur. Cela signifie que nous avons besoin de quatre bits d'espace de stockage

0000 

Chaque bit, lorsqu'il est réglé individuellement, a une représentation unique en décimal

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

Une façon courante de mettre en œuvre c'est avec des masques de bits pour représenter chaque option . Les niveaux d'erreur de PHP sont faits de cette façon, par exemple.

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

Ensuite, lorsque vous avez un nombre entier qui représente 0 ou plusieurs de ces drapeaux, vérifiez auprès de l'opérateur de bits et l'opérateur qui est &

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

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

Cet opérateur fonctionne en tant que tel: seuls bits qui sont ensemble dans les deux opérandes sont définis dans le résultat

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

Si nous l'avons vérifié contre OPT_2, le résultat ressemblerait à ceci

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

Merci de tout casser. –

2

citation « l'idée est pas bon, vraiment. Vous mieux passer quelques booléen. Si vous voulez utiliser bitwise puis

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  
} 

»

Qu'est-ce que vous avez fait serait bien si vous étiez vérifier une seule valeur, bien que non optimale, donc vérifier qu'un bit est activé, mais disons que nous voulions être en mesure de correspondre à tout, ou exact nous pourrions avoir les méthodes suivantes

 
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 vous vouliez ensuite élargir en ayant des actions spécifiques ne se passe si le bit x, y, z a été activée, vous pouvez utiliser les éléments suivants

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

Je pense aussi que si vous faites ce qui a été fait dans le citation ci-dessus, les drapeaux peuvent ne pas être la meilleure idée, les valeurs exactes pourraient être meilleures, ce qui a l'avantage de permettre des actions plus discrètes. (0-255) pour 8 bits sur 8 drapeaux distincts

La raison pour laquelle les drapeaux fonctionnent si bien est parce que dans la base 2 "8" ne contient pas "4", et "2" ne contient pas "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

Les '! = 0' ne sont pas nécessaires. –

+0

@Kendall Hopkins "Explicite est mieux que implicite." vous dit Zen de Python;) – Andrey

8

Il fonctionne à peu près de la même façon dans les deux langues, une comparaison côte à côte:

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

?> 

Notez que vous n'avez absolument pas besoin d'utiliser constantes, je les utilise par habitude. Les deux exemples vont courir, j'ai compilé la version C via gcc -Wall flags.c -o flags. Remplacez flags dans l'un ou l'autre exemple par FLAG_TWO ou FLAG_ALL et (malheureusement) aucune gaufre ne sera faite.

Dans la version C, ne doit pas avoir à chatouiller le préprocesseur, il pourrait très bien être une énumération, etc - c'est un exercice pour le lecteur.

+0

Super, cet exemple est très compréhensible. J'ai essayé de comprendre les opérateurs bit à bit pendant un moment maintenant. Merci d'avoir le code en PHP et en C, puisque je vais utiliser les deux pour ça. –

+0

Pas de problème. @Peter Bailey a fourni la meilleure réponse, je suis content que vous ayez accepté le sien. –

+0

Ce sont deux très bonnes réponses. J'ai essayé d'accepter les deux, n'a pas fonctionné. –

Questions connexes