web-dev-qa-db-fra.com

C/C++ vérifie si un bit est défini dans la variable int.

int temp = 0x5E; // in binary 0b1011110.

Existe-t-il un moyen de vérifier si le bit 3 de temp est 1 ou 0 sans décalage et masquage de bit.

Je veux juste savoir s’il existe une fonction intégrée pour cela ou si je suis obligé d’en écrire une moi-même.

88
Milan

En C, si vous voulez masquer la manipulation de bits, vous pouvez écrire une macro:

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

et l'utiliser de cette façon:

CHECK_BIT(temp, 3)

En C++, vous pouvez utiliser std :: bitset .

139
mouviciel

Vérifiez si le bit N (à partir de 0) est activé:

temp & (1 << N)

Il n'y a pas de fonction intégrée pour cela.

72
Joao da Silva

Je voudrais juste utiliser un std :: bits si c'est C++. Simple. Simple. Aucune chance pour des erreurs stupides.

typedef std::bitset<sizeof(int)> IntBits;
bool is_set = IntBits(value).test(position);

ou que diriez-vous de cette bêtise

template<unsigned int Exp>
struct pow_2 {
    static const unsigned int value = 2 * pow_2<Exp-1>::value;
};

template<>
struct pow_2<0> {
    static const unsigned int value = 1;
};

template<unsigned int Pos>
bool is_bit_set(unsigned int value)
{
    return (value & pow_2<Pos>::value) != 0;
} 

bool result = is_bit_set<2>(value);
21
user21714

Selon cette description des champs de bits , il existe une méthode pour définir et accéder directement aux champs. L'exemple dans cette entrée va:

struct preferences {
    unsigned int likes_ice_cream : 1;
    unsigned int plays_golf : 1;
    unsigned int watches_tv : 1;
    unsigned int reads_books : 1;
}; 

struct preferences fred;

fred.likes_ice_cream = 1;
fred.plays_golf = 1;
fred.watches_tv = 1;
fred.reads_books = 0;

if (fred.likes_ice_cream == 1)
    /* ... */

En outre, il y a un avertissement ici:

Cependant, les membres de bits dans les structures ont des inconvénients pratiques. Premièrement, l'ordre des bits en mémoire dépend de l'architecture et les règles de remplissage de la mémoire varient d'un compilateur à l'autre. En outre, de nombreux compilateurs courants génèrent un code inefficace pour la lecture et l’écriture de membres de bits, et il existe des problèmes de sécurité de threads potentiellement graves liés aux champs de bits (en particulier sur les systèmes multiprocesseurs) car la plupart des machines ne peuvent pas manipuler des ensembles de bits arbitraires en mémoire. mais doit plutôt charger et stocker des mots entiers.

11
gimel

Ouais, je sais que je "n'ai pas" pour le faire de cette façon. Mais j'écris d'habitude:

    /* Return type (8/16/32/64 int size) is specified by argument size. */
template<class TYPE> inline TYPE BIT(const TYPE & x)
{ return TYPE(1) << x; }

template<class TYPE> inline bool IsBitSet(const TYPE & x, const TYPE & y)
{ return 0 != (x & y); }

Par exemple.:

IsBitSet( foo, BIT(3) | BIT(6) );  // Checks if Bit 3 OR 6 is set.

Entre autres choses, cette approche:

  • Accepte les entiers 8/16/32/64 bits.
  • Détecte les appels IsBitSet (int32, int64) à mon insu et sans mon consentement.
  • Modèle en ligne, donc pas de surcharge d’appel de fonction.
  • const & références, donc rien ne nécessite que soit dupliqué/copié. Et nous avons la garantie que le compilateur détectera toutes les fautes de frappe qui tentent de modifier les arguments.
  • 0! = Rend le code plus clair et plus évident. Le principal objectif de l'écriture de code est toujours de communiquer clairement et efficacement avec les autres programmeurs, y compris ceux de moindre compétence.
  • Bien que non applicable à ce cas particulier ... En général, les fonctions basées sur des modèles évitent le problème de l’évaluation des arguments à plusieurs reprises. Un problème connu avec certaines macros #define. 
    Exemple: #define ABS (X) (((X) <0)? - (X): (X)) 
    ABS (i ++);
10
Mr.Ree

Ce que la réponse sélectionnée fait réellement mal. La fonction ci-dessous renvoie la position du bit ou 0 en fonction de l'activation du bit. Ce n'est pas ce que l'affiche demandait.

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

Voici ce que l’affiche cherchait à l’origine. La fonction ci-dessous renvoie 1 ou 0 si le bit est activé et non la position.

#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
8
shocker92

Vous pouvez utiliser un Bitset - http://www.cppreference.com/wiki/stl/bitset/start .

5
yawmark

Utilisez std :: bitset

#include <bitset>
#include <iostream>

int main()
{
    int temp = 0x5E;
    std::bitset<sizeof(int)*CHAR_BITS>   bits(temp);

    // 0 -> bit 1
    // 2 -> bit 3
    std::cout << bits[2] << std::endl;
}
4
Martin York

Il y a, à savoir l'instruction _bittest intrinsic.

4
Dave Van den Eynde

j'essayais de lire un entier 32 bits qui définissait les drapeaux pour un objet dans les fichiers PDF et cela ne fonctionnait pas pour moi

ce qui a changé ça changeait le define:

#define CHECK_BIT(var,pos) ((var & (1 << pos)) == (1 << pos))

l'opérande & retourne un entier avec les drapeaux que tous les deux ont en 1, et il n'a pas été correctement lancé en boolean, cela a fait l'affaire

3
Ismael

J'utilise ceci:

#define CHECK_BIT(var,pos) ( (((var) & (pos)) > 0 ) ? (1) : (0) )

où "pos" est défini comme 2 ^ n (par exemple 1,2,4,8,16,32 ...)

Résultats: 1 si vrai 0 si faux

2
AnthropicDream

Vous pouvez "simuler" le décalage et le masquage: if ((0x5e/(2 * 2 * 2))% 2) ...

2
Leonidas

Pour la solution spécifique x86 de bas niveau, utilisez l’opcode x86 TEST .

Votre compilateur devrait transformer _bittest en cela cependant ...

2
jheriko

Pourquoi ne pas utiliser quelque chose d'aussi simple que cela?

uint8_t status = 255;
cout << "binary: ";

for (int i=((sizeof(status)*8)-1); i>-1; i--)
{
  if ((status & (1 << i)))
  {
    cout << "1";
  } 
  else
  {
    cout << "0";
  }
}

SORTIE: binaire: 11111111

1
zeilja

si vous voulez juste un moyen vraiment codé:

 #define IS_BIT3_SET(var) ( ((var) & 0x04) == 0x04 )

notez cette hw dépendante et supposons que cet ordre de bits 7654 3210 et var est 8 bits.

#include "stdafx.h"
#define IS_BIT3_SET(var) ( ((var) & 0x04) == 0x04 )
int _tmain(int argc, _TCHAR* argv[])
{
    int temp =0x5E;
    printf(" %d \n", IS_BIT3_SET(temp));
    temp = 0x00;
    printf(" %d \n", IS_BIT3_SET(temp));
    temp = 0x04;
    printf(" %d \n", IS_BIT3_SET(temp));
    temp = 0xfb;
    printf(" %d \n", IS_BIT3_SET(temp));
    scanf("waitng %d",&temp);

    return 0;
}

Résulte en:

1 0 1 0

0
simon

Une approche consistera à vérifier dans les conditions suivantes:

if ( (mask >> bit ) & 1)

Un programme d'explication sera:

#include <stdio.h>

unsigned int bitCheck(unsigned int mask, int pin);

int main(void){
   unsigned int mask = 6;  // 6 = 0110
   int pin0 = 0;
   int pin1 = 1;
   int pin2 = 2;
   int pin3 = 3;
   unsigned int bit0= bitCheck( mask, pin0);
   unsigned int bit1= bitCheck( mask, pin1);
   unsigned int bit2= bitCheck( mask, pin2);
   unsigned int bit3= bitCheck( mask, pin3);

   printf("Mask = %d ==>>  0110\n", mask);

   if ( bit0 == 1 ){
      printf("Pin %d is Set\n", pin0);
   }else{
      printf("Pin %d is not Set\n", pin0);
   }

    if ( bit1 == 1 ){
      printf("Pin %d is Set\n", pin1);
   }else{
      printf("Pin %d is not Set\n", pin1);
   }

   if ( bit2 == 1 ){
      printf("Pin %d is Set\n", pin2);
   }else{
      printf("Pin %d is not Set\n", pin2);
   }

   if ( bit3 == 1 ){
      printf("Pin %d is Set\n", pin3);
   }else{
      printf("Pin %d is not Set\n", pin3);
   }
}

unsigned int bitCheck(unsigned int mask, int bit){
   if ( (mask >> bit ) & 1){
      return 1;
   }else{
      return 0;
   }
}

Sortie:

Mask = 6 ==>>  0110
Pin 0 is not Set
Pin 1 is Set
Pin 2 is Set
Pin 3 is not Set
0
Michi

Bien qu’il soit assez tard pour répondre, il existe un moyen simple de déterminer si le nième bit est activé ou non, en utilisant simplement les opérateurs mathématiques POWER et MODULUS.

Disons que nous voulons savoir si "temp" a le nième bit activé ou non. L'expression booléenne suivante donnera true si le bit est défini, 0 sinon.

  • (temp MODULUS 2 ^ N + 1> = 2 ^ N)

Prenons l'exemple suivant:

  • int temp = 0x5E; // en binaire 0b1011110 // BIT 0 est LSB

Si je veux savoir si le 3ème bit est activé ou non, je reçois

  • (94 MODULUS 16) = 14> 2 ^ 3

Donc, l'expression renvoie vrai, indiquant que le troisième bit est défini.

0
Ouroboros