Побітові АБО проти додавання прапорів


16

Я бачив, як інші раніше використовували побітові або АБО для поєднання прапорів:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN | JUMP | SHOOT;

Це також я роблю.

Але я також бачив деякі (не так багато) комбіновані прапори, використовуючи додавання:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN + JUMP + SHOOT;

Хто з них "читабельніший"? (На вашу думку, хто більше людей визнає?) Який "стандартний" спосіб це зробити? Який тобі більше подобається?


Це питання ТО. Розглянемо , використовуючи щось на зразок 1<<0, 1<<1, 1<<2і так далі. Коли у вас багато прапорів, він стає більш читабельним, більш ремонтованим, менш схильним до помилок. Наприклад, якщо ви запакуєте всі 64 біти 64-бітного int, ви дійсно хочете уникнути помилок :) 1Важливо, як ви представляєте . Для 64-бітового цілого числа в VS2010 я думаю, що воно є 1UI64, або щось подібне. Використання неправильного типу може вас укусити.
Робота

3
@Job: Не питання про StackOverflow, оскільки це питання про читабельність, розпізнаваність, уподобання та найкращі практики. Немає єдиної об'єктивної відповіді на це; воно тут належить.
Macneil

Відповіді:


34

Побітові-АБО.

Додавання небезпечне.

Розглянемо приклад, коли бандит - це людина, а розлючений бандит - бандит, який говорить і стріляє. Пізніше ви вирішите, що всі бандити повинні стріляти, але ви забули про розлючене визначення бандита і не знімаєте його прапор.

#define PERSON 1 << 0
#define SPEAKS 1 << 1
#define SHOOTS 1 << 2
#define INVINCIBLE 1 << 3
const byte bandit = PERSON | SHOOTS;                    // 00000101
const byte angryBandit_add = bandit + SPEAKS + SHOOTS;  // 00001011 error
const byte angryBandit_or = bandit | SPEAKS | SHOOTS;   // 00000111 ok

Якщо ви використовували angryBandit_addвашу гру, тепер виникла бдивовижна логічна помилка - розлючених бандитів, які не можуть стріляти або бути вбитими.

Якщо ви використовували angryBandit_orнайгірше, що у вас було, це зайве | SHOOTS.

З подібних причин, порозрядне НЕ безпечніше, ніж віднімання для видалення прапорів.


11

порозрядно-АБО передає наміри більш чітко

також, побіт-АБО повинен бути більш ефективним


Дійсно, +1 я також вважаю, що АБО більш чітко зрозуміло, що це прапори, але щодо ефективності існують мови, де побітові операції повільні, наприклад, JavaScript у всіх числах є 64 поплавкові побітові оператори, які повинні робити неявне перетворення на них.
Іво Ветцель

1
Зважаючи на приклад ОП, я не думаю, що один рядок АБО чи додавання не матиме негативного впливу на швидкість виконання програми.
Бляшаний чоловік

1
@Greg: тим більше, що обчислення в цьому прикладі буде зроблено під час компіляції. :-)
Carson63000

На додаток до передачі наміру, це досить часто бачити це багатьма мовами, включаючи ADA, C #, Java ...
Кен Хендерсон

2
"слід" - це дуже велике слово в цій справі. Хоча сьогодні навряд чи ви зіткнетеся з цією проблемою, я маю дуже чіткі спогади про роботу над процесором, який не мав інструкцій по побитові-АБО. Ви можете побитово-І в одній інструкції, і ви можете побитово-XOR в одній інструкції, але побітно-АБО взяли дві: негайну побітну-І, щоб вимкнути біт, і негайно побіжно-XOR, щоб доповнити щойно очищений біт , що, звичайно, це встановило.
Джон Р. Стром
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.