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.
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 :-)
Il suffit de vérifier la valeur de (1 << bit) & byte
. S'il est différent de zéro, le bit est activé.
Soit le nombre num
. Ensuite:
return ((1 << n) & num);
bool isSet(unsigned char b, unsigned char n) { return b & ( 1 << n); }
#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);
}
Une autre approche serait
bool isNthBitSet (unsigned char c, int n) {
return (1 & (c >> n));
}
#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;
}