Самый правильный способ проверки битов в C - PullRequest
0 голосов
/ 05 ноября 2018

Я читаю книгу «Ядро Linux. Разработка. Третье издание». Роберт Лав.

А в разделе softirq это комментарий следующего куска кода:

    u32 pending;
    pending = local_softirq_pending();

    if (pending) {
            struct softirq_action *h;
            /* reset the pending bitmask */
            set_softirq_pending(0);
            h = softirq_vec;
            do {
                    if (pending & 1) /* STEP 4 */
                            h->action(h);
                    h++;
                    pending >>= 1;
            } while (pending);
    }

Он шаг за шагом описывает, что происходит, и самый непонятный для меня шаг - 4:

  1. Если установлен первый бит в ожидании, h-> action (h) называется

У меня есть следующий код, чтобы проверить, установлен ли бит, как в книге:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BIT_SET(n) ((1) << (n))
#define BIT_CLEAR(n) ~((1) << (n))

int main(void)
{
        unsigned char bits = 0x0;

        bits |= BIT_SET(1);

        if (bits & (1 << 1))
                printf("TEST CHECK SET 1\n");

        if (bits & 1)
                printf("TEST CHECK SET 2\n");

        bits &= BIT_CLEAR(1);

        if (!(bits >> 1) & 1UL)
                printf("BITS UNSET\n");

        return 0;
}

скомпилировано с:

gcc main.c -O0 -Wall -Wextra -Werror. 

Я всегда проверяю, установлен ли бит с этим:

if (bits & (1 << n)) 

И мой код выводит примерно так:

TEST CHECK SET 1
BITS UNSET

Почему if (bits & 1) statment не работает ?:

То есть из нескольких вариантов, которые мне следует использовать и что именно нужно проверять?

if (bit & (1 << n))

if ((bit >> n) & 1)

if (bit & n) 

1 Ответ

0 голосов
/ 05 ноября 2018

Я всегда проверяю, установлен ли бит с этим: if (bits & (1 << n))

Это проверяет n -й бит на месте; однако код из книги сдвигает бит в позицию младшего бита до выполнения проверки с помощью bits & 1. Другими словами, к тому времени, когда код достигает значения if (bits & 1), значение bits уже сдвинуто так, что интересующий бит находится в позиции 1 с.

Это похоже на ваш другой чек

if ((bit >> n) & 1)

кроме (bit >> n) часть выполняется путем выполнения bit >>= 1 операции n раз в цикле.

Обратите внимание, что для корректной работы этого кода bit должен быть без знака.

То есть из нескольких вариантов, которые мне следует использовать и что именно нужно проверять?

Вы неверно истолковали последнюю проверку: она не проверяет бит n, она проверяет bit по всей битовой комбинации двоичного представления n.

...