Я не знаком с побитовыми операторами, но, похоже, раньше они использовали для хранения простых настроек.
Мне нужно передать несколько функций включения / выключения функции, и я хотел бы использовать для этого одно целое. Как я могу настроить параметры и прочитать эти параметры?
Вы можете сделать это на 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
его против OPT_2
, результат будет выглядеть следующим образом:
0101 // our options 0010 // the value of OPT_2 ---- 0000 // The decimal integer 0 evaluates as "false" in an expression
Он работает практически так же, как и на обоих языках, в сравнении друг с другом:
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 вам не нужно щекотать препроцессор, это может быть легко перечислить и т. Д. – это упражнение для читателя.
цитата: «Идея не очень хорошая, на самом деле, вам лучше пройти несколько булевых. Если вы хотите использовать поразрядные
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) {// соответствует вашему критерию, как и случай переключения, но в конечном счете не подходит для использования с флагами return $ in === $ match; } function matchAny ($ in, $ match) {// соответствует исходному критерию с более лексическим именем, но возвращает true, если какой-либо из флагов верен return $ in | = $ match; }
если вы тогда хотели бы расширить это, если бы выполнялись только определенные действия, если бит x, y, z был включен, тогда вы могли бы использовать следующие
function matchHas ($ in, $ match) {// более побитовое, чем ===, так как позволяет условно разветвляться на определенные биты, заданные return $ in & = $ match; }
Я также думаю, что если вы делаете то, что было сделано в приведенной выше цитате, флаги могут быть не лучшей идеей, точные значения могут быть лучше, что дает возможность разрешить более скрытые действия. (0-255) для 8-битных над 8 различными флагами
Все причины флагов работают так хорошо, потому что в базе 2 «8» не содержится «4», а «2» не содержит «1».
________________________ | 8 | 4 | 2 | 1 | База 10 Значение | ------------------------ | 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 | ------------------------