Я про это говорю:
Если у нас есть буква «А», которая равна 77 в десятичной системе и 4D в шестнадцатеричной системе. Я ищу самый быстрый способ получить D.
Я думал о двух способах:
Данный x - байт.
x << 4; x >> 4
x %= 16
Любые другие способы? Какой из них быстрее?





Это можно сделать с помощью одной операции И.
x = (x & 0x0F);
Я всегда использую x &= 0x0f
х = х & 15
Вам, вероятно, следует объяснить, что x% n == x & (n - 1)
Я бы посоветовал использовать шестнадцатеричную нотацию при работе с битовыми операциями. Добавляет много читабельности.
Могу я иметь, но ответ Терье превосходит мой как по краткости, так и по ясности.
@mdec, где n - степень двойки
Я согласен с Альнитаком. Мы должны проголосовать за исключительно хорошие ответы и проголосовать против неправильный. Ответ Гленнера (хотя и краткий) не был неправильным.
Это в некоторой степени будет зависеть от архитектуры - переключение вверх и вниз на ARM, вероятно, является самым быстрым способом, однако компилятор должен сделать это за вас. Фактически, все предложенные методы, вероятно, будут оптимизированы компилятором для одного и того же кода.
Некоторые старые процессоры могут сдвигаться только понемногу за раз и не имеют переменного или многократного сдвига. AFAIK, две операции сдвига медленнее, чем одна операция И на каждом процессоре, с которым я когда-либо сталкивался.
Краткость хороша - объяснения лучше :)
x &= 0x0fis, 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 >>= 4will 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
-O1will reduce this to the first answer.
x %= 16even 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.
Очень хорошее объяснение внутренней работы и подводных камней даже таких простых выражений.
«Если бы это был действительно знаковый символ, то вторая операция вызвала бы расширение знака» - не обязательно. Реализациям разрешено заполнение знака или заполнение 0, когда >> используется для отрицательного значения со знаком.
ок - изменено "могло бы вызвать" на "могло бы вызвать". Кстати, я не помню - будет ли операнд без знака char быть повышен до int для правого оператора сдвига? Если бы это было так, это также привело бы к расширению знака.
Есть много хороших ответов, и некоторые из них технически верны.
В более широком смысле следует понимать, что C / C++ не является ассемблером. Задача программиста - попытаться сообщить компилятору намерение, которого вы хотите достичь. Компилятор выберет лучший способ сделать это в зависимости от архитектуры и различных флагов оптимизации.
х & = 0x0F; это наиболее ясный способ сказать компилятору, чего вы хотите достичь. Если в какой-то архитектуре переключение вверх и вниз происходит быстрее, задача компилятора - знать это и делать правильные вещи.
Верно! Давайте позаботимся о наиболее читаемом коде, пусть компилятор позаботится о самом быстром коде.
«сообщить компилятору намерение, чего вы хотите достичь» - эй - это моя фраза! :)
@Rowland: Вы правы, ASCII "A" - 0x41. «M» - это 0x4D.