Я не знаком с побитовыми операторами, но я имею, кажутся ими, раньше хранил простые настройки прежде.
Я должен передать несколько опций включения - выключения функции, и я хотел бы использовать единственное целое число для этого. Как я могу пойти об установке и чтении этих опций?
Вы точно можете это сделать в PHP.
Допустим, у вас есть четыре логических значения, которые вы хотите сохранить в одном значении. Это означает, что нам нужно четыре бита памяти
0000
. Каждый бит, когда он установлен индивидуально, имеет уникальное десятичное представление
0001 = 1 // or 2^0
0010 = 2 // or 2^1
0100 = 4 // or 2^2
1000 = 8 // or 2^3
. Обычный способ реализовать это - использовать битовые маски для представления каждой опции. Например, таким образом выполняются уровни ошибок PHP.
define( 'OPT_1', 1 );
define( 'OPT_2', 2 );
define( 'OPT_3', 4 );
define( 'OPT_4', 8 );
Затем, когда у вас есть целое число, которое представляет 0 или более этих флагов, вы проверяете его с помощью побитового оператора и, который равен &
$options = bindec( '0101' );
// can also be set like this
// $options = OPT_1 | OPT_3;
if ( $options & OPT_3 )
{
// option 3 is enabled
}
Этот оператор работает как таковой: только биты, которые установлены в обоих операндах, являются установлено в результате
0101 // our options
0100 // the value of OPT_3
----
0100 // The decimal integer 4 evaluates as "true" in an expression
. Если мы проверим его по OPT_2
, то результат будет выглядеть так
0101 // our options
0010 // the value of OPT_2
----
0000 // The decimal integer 0 evaluates as "false" in an expression
quote "идея не очень хорошая, на самом деле. лучше передавать несколько булевых чисел. если вы хотите использовать bitwise then
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
}
"
То, что вы сделали, было бы нормально, если бы вы проверяли одно значение, хотя и не оптимально, так что проверка того, что бит включен, но допустим, мы хотим иметь возможность соответствовать любому, или точному, мы могли бы иметь следующие методы
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; }
Если бы вы затем хотели расширить это, имея определенные действия, происходящие только если бит x, y,z был включен, то вы могли бы использовать следующее
function matchHas($in, $match) { // more bitwise than === as allows you to conditionally branch upon specific bits being set return $in &= $match; }
Я также думаю, что если вы делаете то, что было сделано в цитате выше, флаги могут быть не лучшей идеей, точные значения могут быть лучше, что имеет преимущество, позволяя более дискретные действия. (0-255) для 8-битных более 8 отдельных флагов
Вся причина, по которой флаги работают так хорошо, заключается в том, что в основании 2 "8" не содержит "4", а "2" не содержит "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 | ------------------------
Он работает практически одинаково на обоих языках, параллельное сравнение:
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);
?>
Обратите внимание, вам не обязательно использовать константы, я просто использую их по привычке. Оба примера будут работать, я скомпилировал версию C с помощью gcc -Wall flags.c -o flags
. Измените flags
в любом примере на что угодно, кроме FLAG_TWO
или FLAG_ALL
, и (к сожалению) вафли не будут.
В версии C вам не нужно щекотать препроцессор, это вполне может быть перечисление и т. Д. - это упражнение для читателя.