C & PHP: Сохранение настроек в целых числах с помощью побитовых операторов?

Я не знаком с побитовыми операторами, но, похоже, раньше они использовали для хранения простых настроек.

Мне нужно передать несколько функций включения / выключения функции, и я хотел бы использовать для этого одно целое. Как я могу настроить параметры и прочитать эти параметры?

Вы можете сделать это на 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 |
  ------------------------