Какой самый быстрый способ получить 4 младших бита в байте (C ++)? - PullRequest
7 голосов
/ 17 ноября 2008

Я говорю об этом:

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

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

Учитывая, что x является байтом.

  1. x << 4; x >> 4

  2. x %= 16

Есть еще способы? Какой из них быстрее?

Ответы [ 6 ]

37 голосов
/ 17 ноября 2008

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

  • x &= 0x0f

это, конечно, правильный ответ. Он точно выражает намерение того, чего вы пытаетесь достичь, и на любой разумной архитектуре всегда компилируется до минимального количества инструкций (т.е. 1). Используйте шестнадцатеричный, а не десятичный, когда вы помещаете константы в побитовый оператор.

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

будет работать, только если ваш 'байт' является правильным беззнаковым типом. Если на самом деле это был символ со знаком, то вторая операция может привести к расширению знака (т. Е. Ваш первоначальный бит 3 также появится в битах 4-7).

без оптимизации, конечно, потребуется 2 инструкции, но с GCC на OSX, даже -O1 уменьшит это до первого ответа.

  • x %= 16

даже без включенного оптимизатора ваш компилятор почти наверняка сделает все правильно и превратит эту дорогую операцию div / mod в первый ответ. Однако это может быть сделано только для двух сил, и эта парадигма не делает совершенно очевидным, чего вы пытаетесь достичь.

22 голосов
/ 17 ноября 2008

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

10 голосов
/ 17 ноября 2008

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

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

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

4 голосов
/ 17 ноября 2008

Одиночная операция И может сделать это.

x = (x & 0x0F);
2 голосов
/ 17 ноября 2008

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

0 голосов
/ 17 ноября 2008

х = х & 15

...