Suche…


Bemerkungen

Bit-Shift-Operationen sind nicht für alle Prozessorarchitekturen portierbar. Unterschiedliche Prozessoren können unterschiedliche Bitbreiten haben. Mit anderen Worten, wenn Sie geschrieben haben

int a = ~0;
int b = a << 1;

Dieser Wert unterscheidet sich auf einer 64-Bit-Maschine gegenüber einer 32-Bit-Maschine oder von einem x86-basierten Prozessor zu einem PIC-basierten Prozessor.

Die Endianität muss nicht für die bitweisen Operationen selbst berücksichtigt werden, das heißt, die Verschiebung nach rechts ( >> ) verschiebt die Bits in Richtung des niedrigstwertigen Bits, und ein XOR führt eine Exklusivität oder die Bits aus. Endian-Ness muss nur bei den Daten selbst berücksichtigt werden. Wenn also die Endian-Ness für Ihre Anwendung ein Problem ist, ist dies unabhängig von bitweisen Operationen ein Problem.

& - bitweise AND

int a = 6;     // 0110b  (0x06)
int b = 10;    // 1010b  (0x0A)
int c = a & b; // 0010b  (0x02)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Ausgabe

a = 6, b = 10, c = 2

Warum

Ein bisschen weise AND arbeitet auf Bitebene und verwendet die folgende boolesche Wahrheitstabelle:

TRUE  AND TRUE  = TRUE
TRUE  AND FALSE = FALSE
FALSE AND FALSE = FALSE

Wenn der Binärwert für a ( 0110 ) und der Binärwert für b ( 1010 ) AND -verknüpft sind, erhalten wir den Binärwert von 0010 :

int a = 0 1 1 0
int b = 1 0 1 0 &
        ---------
int c = 0 0 1 0

Das bitweise UND-Element ändert den Wert der ursprünglichen Werte nicht, es sei denn, er ist dem bitweisen Zuweisungsoperator &= ausdrücklich zugewiesen:

int a = 5;  // 0101b  (0x05)
a &= 10;    // a = 0101b & 1010b

| - bitweise ODER

int a = 5;     // 0101b  (0x05)
int b = 12;    // 1100b  (0x0C)
int c = a | b; // 1101b  (0x0D)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Ausgabe

a = 5, b = 12, c = 13

Warum

Ein bisschen weise OR arbeitet auf Bitebene und verwendet die folgende boolesche Wahrheitstabelle:

true OR true = true
true OR false = true
false OR false = false

Wenn der Binärwert für a ( 0101 ) und der Binärwert für b ( 1100 ) zusammen OR , erhalten wir den Binärwert von 1101 :

int a = 0 1 0 1
int b = 1 1 0 0 |
        ---------
int c = 1 1 0 1

Das bitweise ODER ändert den Wert der ursprünglichen Werte nicht, es sei denn, es ist ausdrücklich der Verwendung des bitweisen Zuweisungsoperators |= zugewiesen:

int a = 5;  // 0101b  (0x05)
a |= 12;    // a = 0101b | 1101b

^ - bitweise XOR (exklusives ODER)

int a = 5;     // 0101b  (0x05)
int b = 9;     // 1001b  (0x09)
int c = a ^ b; // 1100b  (0x0C)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Ausgabe

a = 5, b = 9, c = 12

Warum

Ein bisschen XOR (exklusiv oder) arbeitet auf Bitebene und verwendet die folgende boolesche Wahrheitstabelle:

true OR true = false
true OR false = true
false OR false = false

Beachten Sie, dass bei einer XOR-Operation true OR true = false Wo wie bei den Operationen true AND/OR true = true , ist dies die Exklusivität der XOR-Operation.

Wenn der binäre Wert für a ( 0101 ) und der binäre Wert für b ( 1001 ) zusammen XOR 'sind, erhalten wir den binären Wert von 1100 :

int a = 0 1 0 1
int b = 1 0 0 1 ^
        ---------
int c = 1 1 0 0

Das bitweise XOR ändert den Wert der ursprünglichen Werte nicht, es sei denn, es ist ausdrücklich der Verwendung des bitweisen Zuweisungsoperators ^= zugewiesen:

int a = 5;  // 0101b  (0x05)
a ^= 9;    // a = 0101b ^ 1001b

Das bitweise XOR kann auf viele Arten verwendet werden und wird häufig in Bitmaskenoperationen zur Verschlüsselung und Komprimierung verwendet.

Hinweis: Das folgende Beispiel wird häufig als Beispiel für einen schönen Trick gezeigt. Sollte aber nicht im Produktionscode verwendet werden (es gibt bessere Möglichkeiten, mit std::swap() dasselbe Ergebnis zu erzielen).

Sie können eine XOR-Operation auch verwenden, um zwei Variablen ohne temporäre Auslagerungen auszutauschen:

int a = 42;
int b = 64;

// XOR swap
a ^= b;
b ^= a;
a ^= b;

std::cout << "a = " << a << ", b = " << b << "\n";

Um dies zu produzieren, müssen Sie eine Prüfung hinzufügen, um sicherzustellen, dass sie verwendet werden kann.

void doXORSwap(int& a, int& b)
{
    // Need to add a check to make sure you are not swapping the same
    // variable with itself. Otherwise it will zero the value.
    if (&a != &b)
    {
        // XOR swap
        a ^= b;
        b ^= a;
        a ^= b;
    }
}

Obwohl es in der Isolation wie ein schöner Trick aussieht, ist es in echtem Code nicht nützlich. xor ist keine logische Basisoperation, sondern eine Kombination von anderen: a ^ c = ~ (a & c) & (a | c)

auch in 2015+ Compiler-Variablen können binär zugewiesen werden:

int cn=0b0111;

~ - bitweise NICHT (unäre Ergänzung)

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)

std::cout << "a = " << static_cast<int>(a) <<
             ", b = " << static_cast<int>(b) << std::endl;

Ausgabe

a = 234, b = 21

Warum

Ein bisschen NOT (unäres Komplement) arbeitet auf Bitebene und dreht einfach jedes Bit. Wenn es eine 1 , wird es in eine 0 geändert, wenn es eine 0 , wird es in eine 1 geändert. Das bitweise NICHT hat den gleichen Effekt wie XOR, wenn ein Wert gegen den Maximalwert für einen bestimmten Typ gesetzt wird:

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)
unsigned char c = a ^ ~0;

Das bitweise NICHT kann auch ein bequemer Weg sein, den Maximalwert für einen bestimmten ganzzahligen Typ zu überprüfen:

unsigned int i = ~0;
unsigned char c = ~0;

std::cout << "max uint = " << i << std::endl <<
             "max uchar = " << static_cast<short>(c) << std::endl;

Das bitweise NICHT ändert den Wert des ursprünglichen Werts nicht und hat keinen zusammengesetzten Zuweisungsoperator, so dass Sie beispielsweise kein a ~= 10 ausführen können.

Das bitweise NOT ( ~ ) sollte nicht mit dem logischen NOT ( ! ) Verwechselt werden; Wo ein bisschen NICHT jedes Bit umkehrt, verwendet ein logisches NICHT den gesamten Wert, um seine Operation auszuführen, dh (!1) != (~1)

<< - Linksverschiebung

int a = 1;      // 0001b
int b = a << 1; // 0010b

std::cout << "a = " << a << ", b = " << b << std::endl;

Ausgabe

a = 1, b = 2

Warum

Die bitweise Verschiebung nach links verschiebt die Bits des linken Werts ( a ) um die auf der rechten Seite angegebene Zahl ( 1 ), wobei die niederwertigsten Bits im Wesentlichen mit 0 aufgefüllt werden, wodurch der Wert 5 (binär 0000 0101 ) nach links verschoben wird 4 mal (zB 5 << 4 ) ergibt den Wert 80 (binär 0101 0000 ). Sie können feststellen, dass das Verschieben eines Wertes um 1 Mal nach links auch mit dem Multiplizieren des Werts mit 2 identisch ist. Beispiel:

int a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a <<= 1;
}

a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a *= 2;
}

Es sei jedoch darauf hingewiesen, dass die Linksverschiebungsoperation alle Bits einschließlich des Vorzeichenbits nach links verschiebt. Beispiel:

int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1;     // 1111 1111 1111 1111 1111 1111 1111 1110

std::cout << "a = " << a << ", b = " << b << std::endl;

Mögliche Ausgabe: a = 2147483647, b = -2

Während einige Compiler Ergebnisse liefern, die wie erwartet erscheinen, sollte beachtet werden, dass wenn Sie eine vorzeichenbehaftete Zahl verschieben, sodass das Vorzeichenbit betroffen ist, das Ergebnis undefiniert ist . Es ist auch undefiniert, wenn die Anzahl der Bits, um die Sie verschieben möchten, eine negative Zahl ist oder größer ist als die Anzahl der Bits, die der Typ links enthalten kann. Beispiel:

int a = 1;
int b = a << -1;  // undefined behavior
char c = a << 20; // undefined behavior

Die bitweise Verschiebung nach links ändert den Wert der ursprünglichen Werte nicht, es sei denn, sie ist speziell dem bitweisen Zuweisungsoperator <<= zugewiesen:

int a = 5;  // 0101b
a <<= 1;    // a = a << 1;

>> - Rechtsverschiebung

int a = 2;      // 0010b
int b = a >> 1; // 0001b

std::cout << "a = " << a << ", b = " << b << std::endl;

Ausgabe

a = 2, b = 1

Warum

Die Verschiebung des rechten Bits nach rechts verschiebt die Bits des linken Werts ( a ) um die rechts angegebene Zahl ( 1 ); Es sollte beachtet werden, dass die Operation einer Rechtsverschiebung zwar Standard ist, aber was mit den Bits einer Rechtsverschiebung bei einer vorzeichenbehafteten negativen Zahl geschieht , ist durch die Implementierung definiert und kann daher nicht als tragbar angesehen werden.

int a = -2;    
int b = a >> 1; // the value of b will be depend on the compiler

Es ist auch undefiniert, wenn die Anzahl der Bits, um die Sie verschieben möchten, eine negative Zahl ist. Beispiel:

int a = 1;
int b = a >> -1;  // undefined behavior

Die bitweise Verschiebung nach rechts ändert den Wert der ursprünglichen Werte nicht, es sei denn, sie ist ausdrücklich der Verwendung des zusammengesetzten Operators für die bitweise Zuweisung >>= zugewiesen:

int a = 2;  // 0010b
a >>= 1;    // a = a >> 1;


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow