Что сравнивается в этом побитовом операторе if?

Я пытаюсь понять функцию, которая была написана кем-то другим, но мне трудно со вторым оператором if, который находится внутри цикла for. Может кто-нибудь объяснить логику здесь? Что на самом деле сравнивается?

Данные для таблицы CMS_ROLE имеют следующие столбцы: ID, ROLE_MASK, ROLE_KEY. Оба varchar (100). ROLE_MASK — это заголовок, такой как менеджер, автор, администратор и т. Д. ROLE_KEY — это номер, присвоенный ROLE_MASK.

1 | Менеджер | 1

2 | Автор | 4

3 | Admin | 9

 function roleKeys($roleMask)
{
$roleKeys = array();
$this->queryBuilder
->select(array("ROLE_MASK", "ROLE_KEY"))
->from("CMS_ROLE");
$roles = $this->queryBuilder->execute()->fetchAll();
foreach ($roles as $role) {
if ($roleMask) {
if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];

} else if (!$role["ROLE_MASK"]) {
$roleKeys[] = $role["ROLE_KEY"];
}
}
return $roleKeys;
}

ОБНОВИТЬ:

Вот мой вывод var_dump. Все еще в замешательстве.

echo "intval role_mask : " ; var_dump(intval($role["ROLE_MASK"]));
echo "if statement : " ; var_dump( intval($roleMask & intval($role["ROLE_MASK"])));
echo "<br />-----------------<br />";

intval role_mask :
int 0
if statement :
int 0

-----------------
intval role_mask :
int 1
if statement :
int 1

-----------------
intval role_mask :
int 2
if statement :
int 0

-----------------
intval role_mask :
int 4
if statement :
int 0

-----------------
intval role_mask :
int 8
if statement :
int 0

-----------------
intval role_mask :
int 16
if statement :
int 0

-----------------
intval role_mask :
int 32
if statement :
int 32

-----------------
intval role_mask :
int 99
if statement :
int 97

-----------------
intval role_mask :
int 98
if statement :
int 96

-----------------
intval role_mask :
int 97
if statement :
int 97

-----------------

1

Решение

Ниже приведено простое объяснение того, как работает побитовый оператор, оно должно помочь вам понять, что программист намеревался сделать

Предположим следующие значения для переменных:

СЛУЧАЙ 1:

$roleMask = 5;
$role["ROLE_MASK"] = 5;

для оператора if:

if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];

состояние:

((intval($roleMask) & intval($role["ROLE_MASK"]) == intval($roleMask))

решается следующим образом:

5 in binary = 101

Затем 101 сравнивается с 101 по битам
побитовое И следует этим правилам:

1 compared to 1 = 1
1 compared to 0 = 0
0 compared to 0 = 0
0 compared to 1 = 0

это дает:

1 compared to 1 = 1
0 compared to 0 = 0
1 compared to 1 = 1

101 в десятичном виде это 5, так

(5 & 5) = 5

Оператор if становится

if ((5 & 5) == 5) $roleKeys[] = $role["ROLE_KEY"];

который разрешает

if (5 == 5) $roleKeys[] = $role["ROLE_KEY"];

СЛУЧАЙ 2:

$roleMask = 6;
$role["ROLE_MASK"] = 7;

для оператора if:

if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];

состояние:

((intval($roleMask) & intval($role["ROLE_MASK"]) == intval($roleMask))

решается следующим образом:

6 in binary = 110
7 in binary = 111

Затем 110 сравнивается с 111 по битам
следуя тем же правилам, что и выше, это дает:

1 compared to 1 = 1
1 compared to 1 = 1
0 compared to 1 = 0

110 в десятичном виде это 6, так

(6 & 7) = 6

Оператор if становится

if ((6 & 7) == 6) $roleKeys[] = $role["ROLE_KEY"];

который разрешает

if (6 == 6) $roleKeys[] = $role["ROLE_KEY"];

ДЕЛО 3:

$roleMask = 7;
$role["ROLE_MASK"] = 4;

для оператора if:

if ((intval($roleMask) & intval($role["ROLE_MASK"])) == intval($roleMask)) $roleKeys[] = $role["ROLE_KEY"];

состояние:

((intval($roleMask) & intval($role["ROLE_MASK"]) == intval($roleMask))

решается следующим образом:

7 in binary = 111
4 in binary = 100

111 тогда сравнивается с 100 бит за битом
следуя тем же правилам, что и выше, это дает:

1 compared to 1 = 1
1 compared to 0 = 0
1 compared to 0 = 0

100 в десятичном виде это 4, так

(7 & 4) = 4

Оператор if становится

if ((7 & 4) == 7) $roleKeys[] = $role["ROLE_KEY"];

который разрешает

if (4 == 7) $roleKeys[] = $role["ROLE_KEY"];

В этом случае сравнение не проходит проверку .. надеюсь, это поможет

1

Другие решения

Если у вас есть набор флагов $flags и немного маски $bitMaskспособ проверить, установлены ли все биты в битовой маске:

if (($flags & $bitMask) == $bitMask)

Это выражение, которое вы имеете, за исключением аргументов & поменялся местами (что не имеет значения).

Например, скажем, $flags является 0x1110 а также $bitMask является 0x0110, Если вы И эти две ценности вместе, вы получите 0x0110, Это проходит тест, так как это значение равно $bitMask,

Теперь давайте скажем $flags является 0x1110 а также $bitMask является 0x0111, ANDing те вместе производит 0x0110, Это значение делает не матч $bitMask, поэтому тест не пройден. Не все биты в битовой маске были установлены в переменной flags, а именно — самый правый бит.

0