функция для проверки, установлен ли n-й бит в байте - PullRequest
18 голосов
/ 19 января 2012

Мне нужна простая функция C, которая будет возвращать true, если n-й бит в байте установлен на 1.В противном случае он вернет false.

Это критическая функция с точки зрения времени выполнения, поэтому я думаю о наиболее оптимальном способе сделать это.

Ответы [ 7 ]

36 голосов
/ 19 января 2012

Следующая функция может делать то, что вам нужно:

int isNthBitSet (unsigned char c, int n) {
    static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
    return ((c & mask[n]) != 0);
}

Предполагается, что 8-битные байты (не даны в C) и нулевой бит являются старшим битом. Если эти предположения неверны, это просто сводится к расширению и / или переупорядочению массива mask.

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

На безумном уровне оптимизации -O3, gcc дает нам:

isNthBitSet:    pushl   %ebp
                movl    %esp, %ebp
                movl    12(%ebp), %eax
                movzbl  8(%ebp), %edx
                popl    %ebp
                testb   %dl, mask(%eax)
                setne   %al
                movzbl  %al, %eax
                ret
mask:           .byte   -128, 64, 32, 16, 8, 4, 2, 1

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

Просто убедитесь, что вы оцениваете любое решение, которое вам предоставляется, включая это (a) . Мантра номер один в оптимизации - «Мера, не угадай!»

Если вы хотите узнать, как работают побитовые операторы, см. здесь . Упрощенная И-версия только ниже.

Операция AND & установит бит в цель только в том случае, если оба бита установлены в источниках тэво. Соответствующая таблица:

AND | 0 1
----+----
 0  | 0 0
 1  | 0 1

Для данного значения char мы используем однобитовые битовые маски, чтобы проверить, установлен ли бит. Допустим, у вас есть значение 13, и вы хотите увидеть, установлен ли третий бит из наименее значимого.

Decimal  Binary
  13     0000 1101
   4     0000 0100 (the bitmask for the third-from-least bit).
         =========
         0000 0100 (the result of the AND operation).

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

Отсюда и выражение в выражении return. Значения в справочной таблице mask являются однобитовыми масками:

Decimal  Binary
  128    1000 0000
   64    0100 0000
   32    0010 0000
   16    0001 0000
    8    0000 1000
    4    0000 0100
    2    0000 0010
    1    0000 0001

(а) Я знаю, насколько я хорош, но вы не знаете: -)

25 голосов
/ 19 января 2012

Просто проверьте значение (1 << bit) & byte. Если он ненулевой, бит установлен.

10 голосов
/ 19 января 2012

Пусть число будет num. Тогда:

return ((1 << n) & num);
4 голосов
/ 19 января 2012
bool isSet(unsigned char b, unsigned char n) { return b & ( 1 << n); }
2 голосов
/ 25 января 2016

Другой подход будет

    bool isNthBitSet (unsigned char c, int n) {
      return (1 & (c >> n));
    }
2 голосов
/ 17 декабря 2012
#include<stdio.h>
int main()
{
   unsigned int n,a;
   printf("enter value for n\n");
   scanf("%u",&n);
   pintf("enter value for a:\n");
   scanf("%u",&a);
   a= a|(((~((unsigned)0))>>(sizeof(int)*8-1))<<n);
   printf("%u\n",a);
}   
0 голосов
/ 01 февраля 2018
#include<stdio.h>

int main() 
{
        int data,bit;
        printf("enter data:");
        scanf("%d",&data);
        printf("enter bit position to test:");
        scanf("%d",&bit);
        data&(1<<bit)?printf("bit is set\n"):printf("bit is clear\n");

   return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...