web-dev-qa-db-fra.com

une fonction pour vérifier si le nième bit est défini dans un octet

Je veux une fonction C simple qui renverra true si le n-ème bit d'un octet est défini sur1 Sinon, il retournera faux.

Il s’agit d’une fonction critique en termes de temps d’exécution. Je pense donc à la meilleure façon de le faire.

18
liv2hak

La fonction suivante peut faire ce dont vous avez besoin:

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

Cela suppose 8 octets (pas une donnée en C) et le bit zéro étant le plus grand. Si ces hypothèses sont incorrectes, il s’agit simplement d’agrandir et/ou de réorganiser le tableau mask.

Aucune vérification d'erreur n'est effectuée puisque vous avez cité la vitesse comme la considération la plus importante. Ne pas transmettez une n invalide, ce sera un comportement indéfini.

Au niveau d'optimisation insensé -O3, gcc nous donne:

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

ce qui est assez petit et efficace. Et si vous le rendez statique et suggérez l'inline ou le forcez en ligne comme définition de macro, vous pouvez même contourner le coût d'un appel de fonction.

Assurez-vous simplement de comparer toutes les solutions qui vous sont données, y compris celle-ci. (une). Le mantra numéro un dans l'optimisation est "Mesurer, ne devinez pas!"

Si vous voulez savoir comment fonctionnent les opérateurs au niveau des bits, voir ici . La version simplifiée ET uniquement est ci-dessous.

L'opération AND & définira un bit dans la cible uniquement si les deux bits sont définis dans les sources. Le tableau pertinent est:

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

Pour une valeur char donnée, nous utilisons les masques à bit unique pour vérifier si un bit est défini. Supposons que vous ayez la valeur 13 et que vous souhaitiez savoir si le bit du troisième parmi les moins significatifs est défini.

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

Vous pouvez voir que tous les bits zéro dans le masque ont pour résultat que les bits de résultat équivalents sont zéro. Le bit unique dans le masque laissera essentiellement le bit équivalent dans la valeur transiter par le résultat. Le résultat est alors nul si le bit que nous vérifions est nul ou non nul s'il en est un.

C'est de là que vient l'expression return. Les valeurs de la table de recherche mask correspondent à tous les masques à un seul bit:

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

(une) JE sais à quel point je suis bon, mais vous ne le savez pas :-)

36
paxdiablo

Il suffit de vérifier la valeur de (1 << bit) & byte. S'il est différent de zéro, le bit est activé.

24
Jon

Soit le nombre num. Ensuite:

return ((1 << n) & num);
10
Divya
bool isSet(unsigned char b, unsigned char n) { return b & ( 1 << n); }
4
Keith Nicholas
#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);
}   
2
Eswar

Une autre approche serait

    bool isNthBitSet (unsigned char c, int n) {
      return (1 & (c >> n));
    }
2
martemiev
#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;
}
0
Ankit Kumar