Ошибка побитовой операции?

Я разрабатываю сайт для развлечения и пытаюсь реализовать контроль доступа к каталогам на основе побитовых операторов.
Я определил GUEST = 1, GROUP1 = 15 and GROUP2 = 23

Если я сравню

echo (23 & 1); // print 1 

но если я определяю GUEST, GROUP1 и GROUP2:

define('GUEST', 1);  
define('GROUP1', 15);  
define('GROUP2', 23);  
// and then  
echo (GROUP2 & GUEST); // print 0  
echo USER_GUEST.','.USER_ROLES1.','.USER_ROLES2; // print 1,15,23` 

С GROUP1 проблем нет:

echo (GROUP1 & GUEST); print 1.  

Где я ошибаюсь? какое-то предложение? Спасибо.


Я обнаружил кое-что действительно странное: мои GUEST, GROUP1 и GROUP2 объявлены внутри ini-файла, который я анализирую с помощью функции parse_ini_file(self::$fileName, true); внутри класса. После того, как я проанализировал файл, я рекурсивно определяю пары ключ = значение, определенные в разделе [DEFINE] (простой трюк). Если я прокомментирую свое определение GROUP2=23 и объявлю его внутри текущего скрипта (GROUP2 & GUEST), вернет 1!


person cantabria    schedule 13.08.2010    source источник
comment
Я протестировал ваш код в PHP 4.4 и 5.2 и в обоих случаях echo(GROUP2 & GUEST); печатает 1   -  person webbiedave    schedule 13.08.2010
comment
GROUP2 & GUEST мне тоже возвращает 1.   -  person apaderno    schedule 13.08.2010


Ответы (3)


Убедитесь, что вы используете числа по основанию 2 для своих групп, то есть 1,2,34,8,16,32.... или вы можете наступать друг на друга. Вот правильный способ сделать разрешения в битовом поле.

define('GUEST', 1);  
define('GROUP1', 2);  
define('GROUP2', 4);
$groups |= GUEST;
$groups |= GROUP1;
if($groups & GUEST) {
    // This user is a guest (it is)
}
if($groups & GROUP1) {
    // This user is in group 1 (it is)
}
if($groups & GROUP2) {
    // This user is in group 2 (it is NOT)
}
person Matt Williamson    schedule 13.08.2010
comment
Это совершенно не правильно, 23 & 1 != 0. Судя по другим ответам/комментариям, это была локализованная проблема, но PHP возвращает правильный ответ (1) для всех остальных. - person Michael Mrozek; 13.08.2010
comment
Да, я пропустил то, что он говорил. - person Matt Williamson; 13.08.2010

PHP 5.3:

php > define('GUEST', 1);
php > define('GROUP1', 15);
php > define('GROUP2', 23);
php > echo GROUP2 & GUEST;
1
php > echo GROUP1 & GUEST;
1

Какую версию PHP вы используете?


Артефакто указал на возможную проблему со строкой (e: но, похоже, отозвал свой пост, хм). Снова в 5.3:

php > var_export(GUEST);
1
php > var_export(GROUP1);
15
php > var_export(GROUP2);
23
php > define('GUEST_AS_STRING', '1');
php > var_export(GUEST_AS_STRING);
'1'
php > echo GROUP1 & GUEST_AS_STRING;
1
php > echo GROUP2 & GUEST_AS_STRING;
1

«1» — это 49-й символ. 49 & 15 — это 1, а 49 & 23 — это 17. Я не уверен, что это проблема со строкой...

person Charles    schedule 13.08.2010
comment
Я гуглил, чтобы найти некоторую информацию. На тестовом сервере установлена ​​версия PHP 5.2.9. В данный момент я не могу протестировать его на другой версии - person cantabria; 13.08.2010

Решено.
Я полностью неправильно понял объявление в руководстве по php где в журнале изменений написано:

5.2.4 Имена ключей и разделов, состоящие из чисел, теперь оцениваются как целые числа PHP, поэтому числа, начинающиеся с 0, оцениваются как восьмеричные, а числа, начинающиеся с 0x, оцениваются как шестнадцатеричные.

Совершенно ясно: ключи и имя раздела... не значения!
Функция parse_ini_file() оценивает целые значения как строку PHP, даже если они не заключены в двойные кавычки. Жалко, но так и есть ;-)

Спасибо за ваше сотрудничество

person cantabria    schedule 13.08.2010