C / C ++ prüft, ob ein Bit gesetzt ist, dh int Variable

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

Gibt es eine Möglichkeit zu überprüfen, ob Bit 3 in Temp 1 oder 0 ist, ohne dass Bit verschoben und maskiert wird?

Ich möchte nur wissen, ob es dafür eine eingebaute Funktion gibt, oder bin ich gezwungen, selbst eine zu schreiben.

Mailand
quelle

Antworten:

157

Wenn Sie in C die Bitmanipulation ausblenden möchten, können Sie ein Makro schreiben:

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

und verwenden Sie es auf diese Weise, um das n- te Bit vom rechten Ende aus zu überprüfen :

CHECK_BIT(temp, n - 1)

In C ++ können Sie std :: bitset verwenden .

Mouviciel
quelle
3
Falls Sie einen einfachen Wahrheitswert benötigen, sollte dieser sein !! ((var) & (1 << (pos))).
Eduard - Gabriel Munteanu
10
@Eduard: In C ist alles != 0wahr, warum also die Mühe machen? 1ist genau so wahr wie 0.1415!
Christoph
1
Und falls Sie C ++ verwenden, können (sollten) Sie eine Vorlage anstelle eines Makros schreiben. :)
Jalf
2
In C ist das in Ordnung. Aber diese Art von Makros in C ++. Das ist schrecklich und so offen für Missbrauch. Verwenden Sie std :: bitset
Martin York
5
Ugh std::bitset, wirklich? Sicher, anstatt ein bisschen Arbeit (und möglicherweise einige wirklich nette Vorlagen) zu erledigen, um ein einzelnes Bit zu überprüfen, verwenden Sie einen aufgeblähten Container, der (bei meiner Implementierung) jedes 'Bit' in einem ansonsten nicht verwendeten Bit speichert unsigned long. Was für eine Platzverschwendung!
underscore_d
86

Überprüfen Sie, ob Bit N (ab 0) gesetzt ist:

temp & (1 << N)

Hierfür gibt es keine eingebaute Funktion.

Joao da Silva
quelle
16
+1 für die Erwähnung, dass es bei 0 beginnt, da ich vermute, dass das OP 1-basiert dachte und die akzeptierte Antwort ihn in Schwierigkeiten bringen wird. :)
Jim Buck
Hm. Warum beginnt das bei 0? Was bekommen wir wann 1 << 0? Entschuldigung, verwirrt.
Danijel
6
OK habe es. Wir beginnen mit dem 0. Besitz, dh 1<<01 ohne Schicht (Schicht 0), also1<<0 == 1
Danijel
27

Ich würde nur ein std :: bitset verwenden, wenn es C ++ ist. Einfach. Einfach. Keine Chance für dumme Fehler.

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

oder wie wäre es mit dieser Albernheit

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);
user21714
quelle
4
@ user21714 Ich denke du meintest std :: bitset <8 * sizeof (int)>
iNFINITEi
oder std :: numeric_limits <int> :: digits
Léo Lam
@iNFINITEi std::bitset<CHAR_BIT * sizeof(int)>um noch korrekter zu sein
Xeverous
13

Ja, ich weiß , ich weiß nicht „haben“ es auf diese Weise zu tun. Aber ich schreibe normalerweise:

    /* 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); }

Z.B:

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

Dieser Ansatz ist unter anderem:

  • Platz für 8/16/32/64-Bit-Ganzzahlen.
  • Erkennt IsBitSet (int32, int64) -Anrufe ohne mein Wissen und meine Zustimmung.
  • Inline-Vorlage, also kein Funktionsaufruf Overhead.
  • const & Referenzen, also nichts Bedarf dupliziert / kopiert werden. Und wir sind garantiert, dass der Compiler alle Tippfehler aufnimmt, die versuchen, die Argumente zu ändern.
  • 0! = Macht den Code klarer und offensichtlicher. Der wichtigste Punkt beim Schreiben von Code ist immer die klare und effiziente Kommunikation mit anderen Programmierern, einschließlich solchen mit geringeren Fähigkeiten.
  • Obwohl dies für diesen speziellen Fall nicht anwendbar ist ... Im Allgemeinen vermeiden Vorlagenfunktionen das Problem der mehrfachen Auswertung von Argumenten. Ein bekanntes Problem mit einigen # Define-Makros.
    ZB: # ABS (X) definieren (((X) <0) - (X): (X))
          ABS (i ++);
Mr.Ree
quelle
13

Was die ausgewählte Antwort tut, ist tatsächlich falsch. Die folgende Funktion gibt die Bitposition oder 0 zurück, je nachdem, ob das Bit tatsächlich aktiviert ist. Dies ist nicht das, wonach das Poster gefragt hat.

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

Hier ist, wonach das Poster ursprünglich gesucht hat. Die folgende Funktion gibt entweder eine 1 oder eine 0 zurück, wenn das Bit aktiviert ist und nicht die Position.

#define CHECK_BIT(var,pos) (((var)>>(pos)) & 1)
schocker92
quelle
1
Es hat einige Zeit gedauert, bis ich verstanden habe, was du meinst. Genauer gesagt: Die erste Funktion gibt 2 zur Potenz der Bitposition zurück, wenn das Bit gesetzt ist, andernfalls 0.
lukasl1991
1
Dies ist genau das Problem, auf das ich gerade gestoßen bool has_feature = CHECK_BIT(register, 25);bin, als ich es verwendet habe. Gut zu wissen, dass ich es ohne das doppelte Negieren tun kann.
Jimmio92
11

Nach dieser Beschreibung von Bitfeldern gibt es eine Methode zum direkten Definieren und Zugreifen auf Felder. Das Beispiel in diesem Eintrag lautet:

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)
    /* ... */

Außerdem gibt es dort eine Warnung:

Bitelemente in Strukturen haben jedoch praktische Nachteile. Erstens ist die Reihenfolge der Bits im Speicher architekturabhängig und die Speicherauffüllregeln variieren von Compiler zu Compiler. Darüber hinaus generieren viele gängige Compiler ineffizienten Code zum Lesen und Schreiben von Bitelementen, und es gibt potenziell schwerwiegende Thread-Sicherheitsprobleme in Bezug auf Bitfelder (insbesondere auf Multiprozessorsystemen), da die meisten Maschinen keine beliebigen Sätze von Bits im Speicher manipulieren können. sondern muss stattdessen ganze Wörter laden und speichern.

gimel
quelle
5

Verwenden Sie 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;
}
Martin York
quelle
1
Ein paar Dinge, die hier erwähnenswert sind - Bits [3] geben Ihnen das 4. Bit - Zählen vom LSB zum MSB. Um es locker auszudrücken, es gibt Ihnen das 4. Bit, das von rechts nach links zählt. Außerdem gibt sizeof (int) die Anzahl der Zeichen in einem int an, daher müsste es sich um std :: bitset <sizeof (int) * CHAR_BITS> Bits (temp) und Bits [sizeof (int) * CHAR_BITS - 3] handeln. um die 3. Bitzählung von MSB zu LSB zu testen, was wahrscheinlich die Absicht ist.
Kunststoff Chris
2
Ja, aber ich denke, der Fragesteller (und die Leute, die aus Google-Suchanfragen stammen) verfügen möglicherweise nicht über diese Fähigkeit, und Ihre Antwort könnte sie irreführen.
Kunststoff Chris
Diese Antwort ist schrecklich. Es sollte gelöscht werden.
Adam Burry
Muss der Wert tempnicht reflektiert werden, um ihn zu einem "Big-Endian" zu machen?
JWW
4

Es gibt nämlich die kleinste intrinsische Anweisung.

Dave Van den Eynde
quelle
3
Der Link zeigt "Microsoft Specific" an. Verwenden Sie es nur, wenn Ihr Code nicht portabel sein muss.
Mouviciel
Der Link zeigt "Microsoft Specific" an, ist jedoch ein vom Intel C ++ - Compiler übernommener Link und führt zu einer BT-Anweisung, sodass Sie dies auch mit dem Inline-Assembler tun können. Das macht es natürlich nicht tragbarer.
Dave Van den Eynde
1
Es ist auch spezifisch für die x86-Architektur. Also nein, definitiv nicht tragbar.
Jalf
Ich bin sicher, dass andere Architekturen ähnliche Optionen haben.
Dave Van den Eynde
Der eigentliche Punkt der Eigenheiten besteht darin, dass sie die vorhandene Hardware nutzen und einen Softwareaustausch verwenden, wenn die Hardware dies nicht handhabt.
Eclipse
4

Ich benutze das:

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

wobei "pos" definiert ist als 2 ^ n (ig 1,2,4,8,16,32 ...)

Rückgabe: 1 wenn wahr 0 wenn falsch

AnthropicDream
quelle
2
Ich denke, dies ist die einzig richtige Antwort für C und C ++. Es ist das einzige, das die Anforderung "... ohne Bitverschiebung und Maskierung" einhält. Sie sollten wahrscheinlich explizit angeben, dass 4 = 2^(3-1)für Bitposition 3 verwendet werden soll, da dies Teil der Frage war.
JWW
3

Ich habe versucht, eine 32-Bit-Ganzzahl zu lesen, die die Flags für ein Objekt in PDFs definiert, und das hat bei mir nicht funktioniert

Was behoben wurde, war die Änderung der Definition:

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

Der Operand & gibt eine Ganzzahl mit den Flags zurück, die beide in 1 haben, und es wurde nicht richtig in Boolesche Werte umgewandelt. Dies hat den Trick getan

Ismael
quelle
!= 0würde das gleiche tun. Sie wissen nicht, wie sich die generierten Maschinenanweisungen unterscheiden können.
Adam Burry
2

Sie können das Verschieben und Maskieren "simulieren": if ((0x5e / (2 * 2 * 2))% 2) ...

Leonidas
quelle
Wir könnten eine Liste sortieren, indem wir sie zufällig mischen und testen, ob sie jetzt "sortiert" ist. Beispiel: while (/ * NOT * /! IsSorted ()) {RandomlyShuffle (); } Aber wir nicht ...
Mr.Ree
Diese Lösung ist äußerst ressourcenschonend und nicht intuitiv. Divs, Muls und Mods sind die drei teuersten Funktionen. Nach Vergleichstests gehören Ands und Shifts zu den billigsten - einige der wenigen, die Sie möglicherweise in weniger als 5 Zyklen erledigen.
Jheriko
Das könnte sein (und ist es nicht, weil moderne Prozessoren Bits und Sprünge verabscheuen). Das OP forderte ursprünglich explizit eine Lösung "ohne Bitverschiebung und Maskierung". Geben Sie also weitere negative Punkte für eine übereinstimmende, aber langsame Antwort. Ich werde den Beitrag nicht löschen, nur weil das OP seine Meinung geändert hat.
Leonidas
Es sieht schwierig aus. Lassen Sie uns diese Antwort nicht ablehnen. Manchmal ist es gut, andere Ansichten zu erkunden.
Viet
2

Verwenden Sie für die Low-Level-x86-spezifische Lösung den x86- TEST- Opcode.

Ihr Compiler sollte _bittest jedoch in dieses verwandeln ...

Jheriko
quelle
Ich würde BT TEST vorziehen, da BT besser zur Aufgabe passt.
u_Ltd.
1

Warum nicht so etwas Einfaches verwenden?

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";
  }
}

AUSGABE: binär: 11111111

zeilja
quelle
wenn sonst mit einem ternären leicht gemacht werden kann : std::cout << (((status & (1 << i)) ? '1' : '0');. Sie sollten die CHAR_BITKonstante von <climits>anstelle von 8-Bit-Codierung verwenden, obwohl Sie in diesem Fall wissen, dass das Ergebnis ohnehin 8 ist, da Sie eineuint8_t
Ryan Haining
0

Wenn Sie nur einen wirklich hartcodierten Weg wollen:

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

Beachten Sie, dass dies hw-abhängig ist und diese Bitreihenfolge 7654 3210 annimmt und var 8 Bit ist.

#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;
}

Ergebnisse in:

1 0 1 0

Simon
quelle
1
Die & -Operation wird für Werte ausgeführt, die nicht in der internen Darstellung enthalten sind.
Remo.D
Hallo Remo.D - Nicht sicher, ob ich Ihren Kommentar verstehe? Ich habe einen 'c'-Code eingefügt, der gut funktioniert.
Simon
Sein Punkt ist, dass es nicht hardwareabhängig ist - IS_BIT3_SET testet immer das 4. niedrigstwertige Bit
Eclipse
0

Obwohl es ziemlich spät ist, jetzt zu antworten, gibt es eine einfache Möglichkeit, herauszufinden, ob das N-te Bit gesetzt ist oder nicht, indem einfach die mathematischen Operatoren POWER und MODULUS verwendet werden.

Nehmen wir an, wir möchten wissen, ob für 'temp' das N-te Bit gesetzt ist oder nicht. Der folgende boolesche Ausdruck gibt true, wenn das Bit gesetzt ist, andernfalls 0.

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

Betrachten Sie das folgende Beispiel:

  • int temp = 0x5E; // in binär 0b1011110 // BIT 0 ist LSB

Wenn ich wissen will, ob das 3. Bit gesetzt ist oder nicht, bekomme ich

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

Der Ausdruck gibt also true zurück und zeigt an, dass das 3. Bit gesetzt ist.

Ouroboros
quelle
0

Ein Ansatz besteht darin, unter folgenden Bedingungen zu prüfen:

if ( (mask >> bit ) & 1)

Ein Erklärungsprogramm wird sein:

#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;
   }
}

Ausgabe:

Mask = 6 ==>>  0110
Pin 0 is not Set
Pin 1 is Set
Pin 2 is Set
Pin 3 is not Set
Michi
quelle
0
#define CHECK_BIT(var,pos) ((var>>pos) & 1)

pos - Bitposition ab 0.

gibt 0 oder 1 zurück.

Artūrs Laizāns
quelle
-1

Ich mache das:

LATGbits.LATG0 = ((m & 0x8)> 0); // um zu überprüfen, ob Bit-2 von m 1 ist

Mathengineer
quelle
-2

Der schnellste Weg scheint eine Nachschlagetabelle für Masken zu sein

oldUser
quelle