Каковы реальные случаи использования следующих побитовых операторов?
- И
- XOR
- НЕ
- ИЛИ
- Сдвиг влево / вправо
language-agnostic
bitwise-operators
Louis Go
источник
источник
Ответы:
Битовые поля (флаги)
Это наиболее эффективный способ представления чего-либо, состояние которого определяется несколькими свойствами «да или нет». ACL являются хорошим примером; если у вас есть, скажем, 4 дискретных разрешения (чтение, запись, выполнение, изменение политики), лучше хранить их в 1 байте, а не в пустой 4. Они могут быть сопоставлены с типами перечисления во многих языках для дополнительного удобства.
Связь через порты / сокеты
всегда включает в себя контрольные суммы, четность, стоп-биты, алгоритмы управления потоком и т. Д., Которые обычно зависят от логических значений отдельных байтов, а не от числовых значений, поскольку носитель может передавать только один бит в время.
Сжатие, шифрование
Оба они сильно зависят от побитовых алгоритмов. Посмотрите на алгоритм deflate для примера - все в битах, а не в байтах.
Конечные автоматы
Я говорю в первую очередь о типах, встроенных в некоторые аппаратные средства, хотя их можно найти и в программном обеспечении. Это комбинаторный характер - они могут буквально получать «скомпилированный» вниз на кучу логических вентилей, поэтому они должны быть выражены как
AND
,OR
,NOT
и т.д.Графика Здесь едва ли достаточно места, чтобы попасть в каждую область, где эти операторы используются в графическом программировании.
XOR
(или^
) здесь особенно интересно, потому что применение одного и того же ввода во второй раз приведет к отмене первого. Старые графические интерфейсы использовались для подсветки выбора и других наложений, чтобы исключить необходимость дорогостоящих перерисовок. Они все еще полезны в медленных графических протоколах (например, удаленный рабочий стол).Это были только первые несколько примеров, которые я привел - это далеко не полный список.
источник
Это странно?
Это делится на два (даже)?
источник
Вот некоторые распространенные идиомы, касающиеся флагов, хранящихся в виде отдельных битов.
Установите флаг Chargeable:
Снимите флажок CallerIDMissing:
Проверьте, установлены ли CallerIDMissing и Chargeable:
источник
Я использовал побитовые операции при реализации модели безопасности для CMS. У него были страницы, к которым могли обращаться пользователи, если они были в соответствующих группах. Пользователь может быть в нескольких группах, поэтому нам нужно было проверить, нет ли пересечения между группами пользователей и группами страниц. Таким образом, мы присвоили каждой группе уникальный идентификатор степени 2, например:
Мы ИЛИ эти значения вместе, и храним значение (как один int) со страницей. Например, если к странице могут обращаться группы A и B, мы сохраняем значение 3 (двоичное значение 00000011) в качестве контроля доступа к страницам. Во многом таким же образом мы храним значение идентификаторов групп ORed вместе с пользователем, чтобы представлять, в каких группах они находятся.
Таким образом, чтобы проверить, может ли данный пользователь получить доступ к данной странице, вам просто нужно объединить значения AND и проверить, не является ли это значение ненулевым. Это очень быстро, поскольку эта проверка реализована в одной инструкции, без зацикливания, без обходов базы данных.
источник
Низкоуровневое программирование является хорошим примером. Например, вам может потребоваться записать определенный бит в регистр с отображением в памяти, чтобы заставить какое-то устройство выполнить то, что вы хотите:
Кроме того ,
htonl()
иhtons()
реализуются с использованием&
и|
операторов (на машинах , у которых порядок байт (Byte заказ) не соответствует сетевой заказ):источник
htons()
иhtonl()
являются функциями POSIX , чтобы менять местамиshort
илиlong
от хоста (h
) байтов к сети (n
порядок байтов).htonl()
для 32-битногоint
значения?long
означает 64-битные во многих языках.Я использую их, например, для получения значений RGB (A) из упакованных значений цвета.
источник
(a & b) >> c
это более чем в 5 раз быстрееa % d / e
(оба способа извлечь одно значение цвета из целого, представляющего ARGB). Соответственно 6,7 с и 35,2 с за 1 млрд итераций.%
это не оператор Modulus, а оператор Remainder. Они эквивалентны для положительных значений, но отличаются от отрицательных. Если вы предоставляете соответствующие ограничения (например, передаваяuint
вместоint
), то оба примера должны иметь одинаковую скорость.Когда у меня есть куча логических флагов, мне нравится хранить их все в int.
Я получаю их, используя побитовое И Например:
и т.п.
источник
if (flags.feature_one_is_one) { // turn on feature }
. Это в стандарте ANSI C, поэтому переносимость не должна быть проблемой.& = AND:
маскировать определенные биты.
Вы определяете конкретные биты, которые должны отображаться или не отображаться. 0x0 & x очистит все биты в байте, в то время как 0xFF не изменит x. 0x0F отобразит биты в нижнем клочке.
Преобразование:
чтобы преобразовать более короткие переменные в более длинные с идентификатором бита, необходимо отрегулировать биты, потому что -1 в int равно 0xFFFFFFFF, а -1 в длинном 0xFFFFFFFFFFFFFFFF. Для сохранения идентичности вы применяете маску после конвертации.
| = ИЛИ
Установить биты. Биты будут установлены независимо, если они уже установлены. Многие структуры данных (битовые поля) имеют флаги, такие как IS_HSET = 0, IS_VSET = 1, которые могут быть установлены независимо. Чтобы установить флаги, вы применяете IS_HSET | IS_VSET (в Си и сборке это очень удобно читать)
^ = XOR
Найти биты, которые являются одинаковыми или разными.
~ = НЕ
переворачивать биты.
Можно показать, что с помощью этих операций могут быть реализованы все возможные локальные битовые операции. Поэтому, если хотите, вы можете реализовать инструкцию ADD только с помощью битовых операций.
Несколько замечательных хаков:
http://www.ugcs.caltech.edu/~wnoise/base2.html
http://www.jjj.de/bitwizardry/bitwizardrypage.html
источник
= ~
, а не|=
ИЛИ.& = AND
- Почему я хочу очистить все биты, почему я хочу получить неизмененную версию байта, и что мне делать с нижним полубайтом?xor
сам по себе. Я могу придумать несколько причин, по которым вы захотите извлечь нижний кусок. Особенно, если этот нижний клочок является частью структуры данных, и вы хотите использовать его как маску илиOR
другую структуру.Шифрование - это все побитовые операции.
источник
Вы можете использовать их как быстрый и грязный способ хэширования данных.
источник
Я просто использовал bitwise-XOR (
^
) около трех минут назад, чтобы вычислить контрольную сумму для последовательной связи с ПЛК ...источник
Побитовый & используется для маскировки / извлечения определенной части байта.
1 байтовая переменная
Специально оператор сдвига (<< >>) часто используется для расчетов.
источник
Это пример для чтения цветов из растрового изображения в байтовом формате.
Я надеюсь, что эти крошечные примеры помогут ....
источник
В отвлеченном мире современного современного языка не так уж много. Файловый ввод-вывод является простым, который приходит на ум, хотя он выполняет побитовые операции над чем-то уже реализованным и не реализует то, что использует побитовые операции. Тем не менее, в качестве простого примера, этот код демонстрирует удаление атрибута только для чтения в файле (чтобы его можно было использовать с новым FileStream, указывающим FileMode.Create) в c #:
Что касается пользовательских реализаций, вот недавний пример: я создал «центр сообщений» для отправки защищенных сообщений из одной установки нашего распределенного приложения в другую. По сути, это аналог электронной почты, в комплекте с папками «Входящие», «Исходящие», «Отправленные» и т. Д., Но также гарантированная доставка с квитанциями о прочтении, поэтому есть дополнительные подпапки, помимо «Входящие» и «Отправленные». То, что это означало, было требованием для меня, чтобы в общем определить, что находится «во входящих» или «в отправленной папке». Из отправленной папки мне нужно знать, что прочитано, а что непрочитано. Из того, что непрочитано, мне нужно знать, что получено, а что нет. Я использую эту информацию для построения динамического предложения where, которое фильтрует локальный источник данных и отображает соответствующую информацию.
Вот как составляется перечисление:
Вы видите, что это делает? Используя and & со значением перечисления Inbox InboundMemos, я знаю, что InboundMemosForMyOrders находится в папке входящих.
Вот развернутая версия метода, который создает и возвращает фильтр, который определяет представление для выбранной в данный момент папки:
Чрезвычайно простая, но аккуратная реализация на уровне абстракции, которая обычно не требует побитовых операций.
источник
Кодировка Base64 является примером. Кодировка Base64 используется для представления двоичных данных в виде печатных символов для отправки по электронной почте (и для других целей). Кодирование Base64 преобразует серию 8-битных байтов в 6-битные индексы поиска символов. Битовые операции, сдвиг и «или», «нет» очень полезны для реализации битовых операций, необходимых для кодирования и декодирования Base64.
Это, конечно, только 1 из бесчисленных примеров.
источник
Я удивлен, что никто не выбрал очевидный ответ для эпохи Интернета. Расчет действительных сетевых адресов для подсети.
http://www.topwebhosts.org/tools/netmask.php
источник
Обычно побитовые операции выполняются быстрее, чем умножение / деление. Поэтому, если вам нужно умножить переменную x на 9, вы будете делать
x<<3 + x
это на несколько циклов быстрее, чемx*9
. Если этот код находится внутри ISR, вы сэкономите на времени отклика.Точно так же, если вы хотите использовать массив как циклическую очередь, было бы быстрее (и более элегантно) обрабатывать циклические проверки с помощью побитовых операций. (размер вашего массива должен быть степенью 2). Например: вы можете использовать
tail = ((tail & MASK) + 1)
вместоtail = ((tail +1) < size) ? tail+1 : 0
, если вы хотите вставить / удалить.Также, если вы хотите, чтобы флаг ошибки содержал несколько кодов ошибок вместе, каждый бит может содержать отдельное значение. Вы можете И это с каждым отдельным кодом ошибки в качестве проверки. Это используется в кодах ошибок Unix.
Также n-битное растровое изображение может быть действительно классной и компактной структурой данных. Если вы хотите выделить пул ресурсов размера n, мы можем использовать n-бит для представления текущего состояния.
источник
Кажется, никто не упомянул математику с фиксированной точкой.
(Да, я старый, хорошо?)
источник
Является ли число
x
степенью 2? (Полезно, например, в алгоритмах, где счетчик увеличивается, а действие должно выполняться только логарифмически число раз)Какой старший бит целого числа
x
? (Это, например, может использоваться, чтобы найти минимальную мощность 2, которая больше, чемx
)Какой младший
1
бит целого числаx
? (Помогает найти количество раз, делимое на 2.)источник
x & -x
.Битовые операторы полезны для циклических массивов, длина которых равна степени 2. Как уже упоминалось, побитовые операторы чрезвычайно полезны и используются в флагах , графике , работе в сети , шифровании . Не только это, но они очень быстро. Мой личный фаворит использование в цикле массив без условными . Предположим, у вас есть массив с нулевым индексом (например, индекс первого элемента равен 0), и вам нужно его бесконечно зацикливать. Под неопределенным временем я имею в виду переход от первого элемента к последнему и возвращение к первому. Один из способов реализовать это:
Это самый простой подход, если вы хотите избежать оператора if , вы можете использовать модульный подход следующим образом:
Недостатком этих двух методов является то, что оператор модуля является дорогим, поскольку он ищет остаток после целочисленного деления. И первый метод выполняет оператор if на каждой итерации. Однако с помощью побитового оператора, если длина вашего массива является степенью 2, вы можете легко сгенерировать последовательность
0 .. length - 1
, используя&
оператор (побитовый и), как этоi & length
. Так зная это, код сверху становитсяВот как это работает. В двоичном формате каждое число, являющееся степенью 2, вычитаемое из 1, выражается только единицами. Например, 3 в двоичном виде
11
, 7 - это111
15,1111
и т. Д., Вы поняли. Теперь, что произойдет, если вы&
против любого числа, состоящего только из двоичных чисел? Допустим, мы делаем это:Если
num
оно меньше или равно 7, результат будетnum
потому, что каждый бит&
с 1 равен самому себе. Если значениеnum
больше 7, во время&
работы компьютер будет считать ведущие нули 7, которые, конечно, останутся нулями после&
операции, останется только последняя часть. Как в случае с9 & 7
двоичнымрезультат будет 0001, который равен 1 в десятичном виде и обращается ко второму элементу в массиве.
источник
Я использую их для нескольких вариантов выбора, таким образом я сохраняю только одно значение вместо 10 или более
источник
это также может быть полезно в реляционной модели sql, скажем, у вас есть следующие таблицы: BlogEntry, BlogCategory
Традиционно вы можете создать отношения nn между ними, используя таблицу BlogEntryCategory или, если записей BlogCategory не так много, вы можете использовать одно значение в BlogEntry для ссылки на несколько записей BlogCategory, как это делается с помеченными перечислениями, в большинстве СУБД также есть. очень быстрые операторы для выбора в этом «помеченном» столбце ...
источник
Когда вы хотите изменить только некоторые биты выходов микроконтроллера, но регистр для записи является байтом, вы делаете что-то вроде этого (псевдокод):
Конечно, многие микроконтроллеры позволяют менять каждый бит индивидуально ...
источник
Если вы когда-нибудь захотите рассчитать ваше число мод (%) определенной степенью 2, вы можете использовать
yourNumber & 2^N-1
, которое в этом случае совпадает сyourNumber % 2^N
.Это, вероятно, полезно только в качестве альтернативы операции с модулем с очень большим дивидендом, равным 2 ^ N ... Но даже в этом случае прирост скорости по сравнению с операцией по модулю в моем тесте на .NET 2.0 незначителен. Я подозреваю, что современные компиляторы уже выполняют такие оптимизации. Кто-нибудь знает больше об этом?
источник
%
и операция Remainder, они по-разному относятся к негативам. Однако, если вы перейдетеuint
к%
, компилятор C # будет фактически генерировать машинный код с использованием побитового И, когда второй аргумент имеет заранее известную степень двойки.Я видел их в ролевых системах контроля доступа.
источник
В моем вопросе есть реальное применение -
Отвечать только на первое уведомление WM_KEYDOWN?
При использовании сообщения WM_KEYDOWN в Windows C api bit 30 указывает предыдущее состояние ключа. Значение равно 1, если ключ не работает до отправки сообщения, или ноль, если ключ работает
источник
Они в основном используются для побитовых операций (неожиданность). Вот несколько реальных примеров, найденных в базе кода PHP.
Кодировка символов:
Структуры данных:
База данных драйверов:
Реализация компилятора:
источник
Всякий раз, когда я впервые начал программировать на С, я понимал таблицы истинности и все такое, но не все решали, как на самом деле использовать их, пока я не прочитал эту статью http://www.gamedev.net/reference/articles/article1563.asp (который дает примеры из реальной жизни)
источник
x == 1
иy == 2
, тогдаx || y
оценивается в 1 иx | y
оценивается в 0. Также я не вижу, почемуx^true
это превосходит!x
в любом случае. Это более типично, менее идиоматично, и если этоx
не так,bool
это ненадежно.x^true
он превосходит,!x
-some->complicated().member->lookup ^= true;
нет версий составного присваивания унарных операторов.Я не думаю, что это считается побитовым, но массив ruby определяет операции над множествами через обычные целочисленные побитовые операторы. Так
[1,2,4] & [1,2,3] # => [1,2]
. Аналогично дляa ^ b #=> set difference
иa | b #=> union
.источник
Линейное решение Tower Of Hanoi использует побитовые операции для решения задачи.
Объяснение этого решения можно найти здесь
источник