Каков самый быстрый способ получить 4 младших бита в байте (C++)?

Я про это говорю:

Если у нас есть буква «А», которая равна 77 в десятичной системе и 4D в шестнадцатеричной системе. Я ищу самый быстрый способ получить D.

Я думал о двух способах:

Данный x - байт.

  1. x << 4; x >> 4

  2. x %= 16

Любые другие способы? Какой из них быстрее?

@Rowland: Вы правы, ASCII "A" - 0x41. «M» - это 0x4D.

Adisak 21.10.2009 22:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
1
4 425
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Это можно сделать с помощью одной операции И.

x = (x & 0x0F);
Ответ принят как подходящий

Я всегда использую x &= 0x0f

х = х & 15

Вам, вероятно, следует объяснить, что x% n == x & (n - 1)

mdec 17.11.2008 13:45

Я бы посоветовал использовать шестнадцатеричную нотацию при работе с битовыми операциями. Добавляет много читабельности.

xtofl 17.11.2008 13:47

Могу я иметь, но ответ Терье превосходит мой как по краткости, так и по ясности.

Glenner003 17.11.2008 13:48

@mdec, где n - степень двойки

Sekhat 17.11.2008 14:25

Я согласен с Альнитаком. Мы должны проголосовать за исключительно хорошие ответы и проголосовать против неправильный. Ответ Гленнера (хотя и краткий) не был неправильным.

efotinis 17.11.2008 15:30

Это в некоторой степени будет зависеть от архитектуры - переключение вверх и вниз на ARM, вероятно, является самым быстрым способом, однако компилятор должен сделать это за вас. Фактически, все предложенные методы, вероятно, будут оптимизированы компилятором для одного и того же кода.

Некоторые старые процессоры могут сдвигаться только понемногу за раз и не имеют переменного или многократного сдвига. AFAIK, две операции сдвига медленнее, чем одна операция И на каждом процессоре, с которым я когда-либо сталкивался.

Adisak 21.10.2009 22:45

Краткость хороша - объяснения лучше :)

  • x &= 0x0f

is, of course, the right answer. It exactly expresses the intent of what you're trying to achieve, and on any sane architecture will always compile down to the minimum number of instructions (i.e. 1). Do use hex rather than decimal whenever you put constants in a bit-wise operator.

  • x <<= 4; x >>= 4

will only work if your 'byte' is a proper unsigned type. If it was actually a signed char then the second operation might cause sign extension (i.e. your original bit 3 would then appear in bits 4-7 too).

without optimization this will of course take 2 instructions, but with GCC on OSX, even -O1 will reduce this to the first answer.

  • x %= 16

even without the optimizer enabled your compiler will almost certainly do the right thing here and turn that expensive div/mod operation into the first answer. However it can only do that for powers of two, and this paradigm doesn't make it quite so obvious what you're trying to achieve.

Очень хорошее объяснение внутренней работы и подводных камней даже таких простых выражений.

Terje Mikal 17.11.2008 14:28

«Если бы это был действительно знаковый символ, то вторая операция вызвала бы расширение знака» - не обязательно. Реализациям разрешено заполнение знака или заполнение 0, когда >> используется для отрицательного значения со знаком.

Steve Jessop 17.11.2008 18:27

ок - изменено "могло бы вызвать" на "могло бы вызвать". Кстати, я не помню - будет ли операнд без знака char быть повышен до int для правого оператора сдвига? Если бы это было так, это также привело бы к расширению знака.

Alnitak 17.11.2008 19:30

Есть много хороших ответов, и некоторые из них технически верны.

В более широком смысле следует понимать, что C / C++ не является ассемблером. Задача программиста - попытаться сообщить компилятору намерение, которого вы хотите достичь. Компилятор выберет лучший способ сделать это в зависимости от архитектуры и различных флагов оптимизации.

х & = 0x0F; это наиболее ясный способ сказать компилятору, чего вы хотите достичь. Если в какой-то архитектуре переключение вверх и вниз происходит быстрее, задача компилятора - знать это и делать правильные вещи.

Верно! Давайте позаботимся о наиболее читаемом коде, пусть компилятор позаботится о самом быстром коде.

xtofl 17.11.2008 14:58

«сообщить компилятору намерение, чего вы хотите достичь» - эй - это моя фраза! :)

Alnitak 17.11.2008 15:02

Другие вопросы по теме