Объясните эту функцию - PullRequest
       27

Объясните эту функцию

0 голосов
/ 22 сентября 2011

Может кто-нибудь объяснить мне причину, по которой кто-то хотел бы использовать побитовое сравнение? Пример:

int f(int x) {
return x & (x-1); 
}
int main(){
  printf("F(10) = %d", f(10));
}

Это то, что я действительно хочу знать: «Зачем проверять общие биты»

x - любое положительное число.

Ответы [ 8 ]

4 голосов
/ 22 сентября 2011

Битовые операции используются по трем причинам:

  • Вы можете использовать наименьшее возможное пространство для хранения информации
  • Вы можете сравнивать / изменять весь регистр (например, 32, 64,или 128 бит в зависимости от вашего процессора) в одной инструкции процессора, обычно с одним тактом.Это означает, что вы можете выполнять большую работу (определенных типов) ослепительно быстро по сравнению с обычной арифметикой.
  • Это круто, весело и интересно.Программистам нравятся эти вещи, и они часто могут быть отличительной чертой, когда нет различий между методами с точки зрения эффективности / производительности.

Вы можете использовать это для всех видов очень удобных вещей.Например, в моей базе данных я могу хранить много истинной / ложной информации о моих клиентах в крошечном пространстве (один байт может хранить 8 различных истинных / ложных фактов), а затем использовать операции '&' для запроса их статуса:

  • Является ли мой клиент мужским и одиноким и курящим?

    if (customerFlags & (maleFlag | singleFlag | smokerFlag) ==
    (maleFlag | singleFlag | smokerFlag))

  • Является ли мой клиент(любая комбинация) мужчина или холостяк или курильщик?

    if (customerFlags & (maleFlag | singleFlag | smokerFlag) != 0)

  • Является ли мой клиент мужчиной и не холост и не курит)?

    if (customerFlags & (maleFlag | singleFlag | smokerFlag) == 0)

Помимо "проверки общих битов", вы также можете сделать:

  • Определенную арифметику, например value & 15 - намного более быстрый эквивалент value % 16.Это работает только для определенных номеров, но если вы можете использовать его, это может быть большой оптимизацией.

  • Упаковка / распаковка данных.например, цвет часто выражается как 32-битное целое число, которое содержит значения байтов Alpha, Red, Green и Blue.Значение Red может быть извлечено с помощью выражения, подобного red = (value >> 16) & 255; (сдвиньте значение на 16 битных позиций, а затем выделите нижний байт)

    • Манипулирование данными и переброс.Некоторые хитрые трюки могут быть достигнуты с помощью побитовых операций.Например, замена двух целочисленных значений без необходимости использования третьей временной переменной или преобразование значений цвета ARGB в другой формат (например, RGBA или BGRA)
2 голосов
/ 22 сентября 2011

Ur-пример «проверяет, является ли число четным или нечетным»:

unsigned int number = ...;
bool isOdd = (0 != (number & 1));

Более сложные применения включают битовые маски (несколько логических значений в одном целом числе, каждое из которых занимает один бит пространства) и шифрование / хеширование (которые часто включают в себя сдвиг битов, XOR и т. д.)

1 голос
/ 22 сентября 2011

Это не побитовое сравнение .Он не возвращает логическое значение.

Битовые операторы используются для чтения и изменения отдельных битов числа.

n &   0x8   // Peek at bit3
n |=  0x8   // Set bit3
n &= ~0x8   // Clear bit3
n ^=  0x8   // Toggle bit3

Биты используются для экономии места.8 символов занимают намного больше памяти, чем 8 битов в символе.

В следующем примере показано получение диапазона IP-подсети с использованием IP-адреса подсети и маски подсети подсети.

uint32_t mask = (((255 << 8) | 255) << 8) | 255) << 8) | 255;
uint32_t ip   = (((192 << 8) | 168) << 8) |   3) << 8) |   4;

uint32_t first = ip & mask;
uint32_t last  = ip | ~mask;
1 голос
/ 22 сентября 2011

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

У меня часто будет код, похожий на следующий:

volatile uint32_t *flags = 0x000A000;
bool flagA = *flags & 0x1;
bool flagB = *flags & 0x2;
bool flagC = *flags & 0x4;
0 голосов
/ 21 сентября 2012

Ваш пример проверяет, установлен ли x не более 1 бита.f возвращает 0, если x является степенью 2, и ненулевым, если это не так.

0 голосов
/ 22 сентября 2011

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

0 голосов
/ 22 сентября 2011

Ваш конкретный пример проверяет, равны ли два последовательных бита в двоичном представлении 1.

0 голосов
/ 22 сентября 2011

например. если у вас есть несколько флагов состояния, чтобы сэкономить место, вы можете поставить каждый флаг как бит.

так что x, если объявлен как байт, будет иметь 8 флагов.

...