(b & (1 << i)) VS ((b >> i) & 1) C ++ - PullRequest
0 голосов
/ 30 апреля 2018

Часто необходимо представлять тип данных как последовательность битов и извлекать их внутри цикла на всю длину. Хотя я нахожу ((b >> i) & 1) более интуитивным, недавно я увидел книгу, использующую (b&(1<<i)). Является ли какой-либо из них более выгодным или более эффективным, и если один из них, почему?

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Предполагается, что вы используете это для небольшого тестирования (поэтому разница в результате не имеет значения), это зависит от контекста и того, что компилятор делает с ним, и других факторов.

Например, при компиляции с GCC 7.3 для современного x86 они абсолютно одинаковы , оба могут компилироваться в следующую последовательность:

sarx eax, edi, esi
and eax, 1

И при использовании результата для фактического принятия решения (вместо материализации логического значения) код может все же быть таким же. Очевидно, что если код будет таким же, не может быть никакой разницы в эффективности. Clang любит использовать bt и setc (или использовать флаг в cmov или потоке управления, когда это необходимо), но также делает то же самое для обоих фрагментов. MSVC компилирует фрагменты различными способами и, возможно, в некотором смысле «предпочитает» формулировку 1 << i.

Реализация b & (1 << i) буквально (что я не наблюдал ни на одном компиляторе на самом деле) требует дополнительной инструкции для загрузки константы 1 в регистр, хотя это не обязательно означает, что это займет дополнительное время ( хотя это возможно): создание 1 не зависит от всего остального, поэтому оно может выполняться впереди всего остального, а затем сдвиг не зависит от b, поэтому он может выполняться после того, как i готов, но до b.

0 голосов
/ 30 апреля 2018

Что выгоднее?

Зависит от того, какие данные вам нужны.

((b >> i) & 1) gives you a 1 or 0.

(b & (1 << i)) gives you a 0 or 2^i.

Что эффективнее?

Разница в эффективности незначительна между ними. Кроме того, различие в архитектуре и коде отличается.

...