Ricerca…


Osservazioni

Le operazioni di spostamento dei bit non sono trasferibili su tutte le architetture dei processori, i processori diversi possono avere diverse larghezze di bit. In altre parole, se hai scritto

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

Questo valore sarebbe diverso su una macchina a 64 bit rispetto a una macchina a 32 bit o su un processore basato su x86 su un processore basato su PIC.

L'endianità non ha bisogno di essere presa in considerazione per le operazioni bit-wise stesse, cioè lo spostamento a destra ( >> ) sposterà i bit verso il bit meno significativo e uno XOR eseguirà un esclusivo o sui bit. L'endianità deve essere presa in considerazione solo con i dati stessi, ovvero se l'endianità è una preoccupazione per l'applicazione, è una preoccupazione indipendentemente dalle operazioni bit-saggio.

& - AND bit a bit

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;

Produzione

a = 6, b = 10, c = 2

Perché

Un po 'saggio AND opera a livello di bit e utilizza la seguente tabella di verità booleana:

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

Quando il valore binario per a ( 0110 ) e il valore binario per b ( 1010 ) sono AND 'ed insieme otteniamo il valore binario di 0010 :

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

Il bit Wise AND non modifica il valore dei valori originali se non è specificamente assegnato all'utilizzo dell'operatore composto di assegnazione bit saggio &= :

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

| - OR bit a bit

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;

Produzione

a = 5, b = 12, c = 13

Perché

Un po 'saggio OR opera a livello di bit e usa la seguente tabella di verità booleana:

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

Quando il valore binario di a ( 0101 ) e il valore binario di b ( 1100 ) sono OR "ed insieme otteniamo il valore binario di 1101 :

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

L'OR bit-saggio non modifica il valore dei valori originali se non è specificamente assegnato all'utilizzo dell'operatore composto assegnazione bit saggio |= :

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

^ - XOR bit a bit (OR esclusivo)

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;

Produzione

a = 5, b = 9, c = 12

Perché

Un po 'saggio XOR (esclusivo o) opera a livello di bit e utilizza la seguente tabella di verità booleana:

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

Si noti che con un'operazione XOR true OR true = false dove, come con le operazioni true AND/OR true = true , quindi la natura esclusiva dell'operazione XOR.

Usando questo, quando il valore binario di a ( 0101 ) e il valore binario di b ( 1001 ) sono XOR 'ed insieme otteniamo il valore binario di 1100 :

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

Il bit XOR bit non modifica il valore dei valori originali se non è specificamente assegnato all'utilizzo dell'operatore composto assegnazione bit saggio ^= :

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

Il bit XOR può essere utilizzato in molti modi ed è spesso utilizzato nelle operazioni di bit mask per la crittografia e la compressione.

Nota: il seguente esempio viene spesso mostrato come esempio di un bel trucco. Ma non dovrebbe essere usato nel codice di produzione (ci sono modi migliori per std::swap() per ottenere lo stesso risultato).

Puoi anche utilizzare un'operazione XOR per scambiare due variabili senza un temporaneo:

int a = 42;
int b = 64;

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

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

Per la produzione di questo è necessario aggiungere un assegno per assicurarsi che possa essere utilizzato.

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

Quindi anche se sembra un bel trucco in isolamento non è utile nel codice reale. xor non è un'operazione logica di base, ma una combinazione di altre: a ^ c = ~ (a & c) & (a | c)

anche nel 2015 le variabili dei compilatori possono essere assegnate come binarie:

int cn=0b0111;

~ - bit per bit NOT (complemento unario)

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;

Produzione

a = 234, b = 21

Perché

Un po 'saggio NOT (complemento unario) opera a livello di bit e semplicemente capovolge ogni bit. Se è un 1 , è cambiato in uno 0 , se è uno 0 , è cambiato in un 1 . Il bit saggio NON ha lo stesso effetto di XOR un valore rispetto al valore massimo per un tipo specifico:

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

Il bit bit NOT può anche essere un modo conveniente per verificare il valore massimo per un tipo specifico integrale:

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

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

Il bit-saggio NOT non cambia il valore del valore originale e non ha un operatore di assegnazione composto, quindi non puoi fare a ~= 10 per esempio.

Il bit saggio NON ( ~ ) non deve essere confuso con il logico NOT ( ! ); dove un po 'saggio NON capovolgerà ogni bit, un NOT logico userà l'intero valore per eseguire la sua operazione, in altre parole (!1) != (~1)

<< - spostamento a sinistra

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

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

Produzione

a = 1, b = 2

Perché

Il bit shift sinistro sposterà i bit del valore della mano sinistra ( a ) il numero specificato a destra ( 1 ), in pratica riempendo i bit meno significativi con 0, quindi spostando il valore di 5 (binario 0000 0101 ) a sinistra 4 volte (es. 5 << 4 ) produrrà il valore di 80 (binario 0101 0000 ). È possibile notare che lo spostamento di un valore a sinistra 1 volta è uguale a moltiplicare il valore per 2, ad esempio:

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

Ma va notato che l'operazione di spostamento a sinistra sposta tutti i bit a sinistra, incluso il bit di segno, ad esempio:

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;

Uscita possibile: a = 2147483647, b = -2

Mentre alcuni compilatori produrranno risultati che sembrano prevedibili, è opportuno notare che se si lascia un numero con segno maiuscolo in modo che il bit del segno sia interessato, il risultato non è definito . È anche indefinito se il numero di bit che desideri spostare è un numero negativo o è maggiore del numero di bit che il tipo a sinistra può contenere, ad esempio:

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

Il cambio bit left shift non cambia il valore dei valori originali a meno che non sia specificamente assegnato all'utilizzo dell'operatore composto assegnazione bit saggio <<= :

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

>> - spostamento a destra

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

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

Produzione

a = 2, b = 1

Perché

Lo spostamento bit destro corretto sposterà i bit del valore della mano sinistra ( a ) il numero specificato a destra ( 1 ); va notato che mentre l'operazione di un passaggio a destra è standard, ciò che accade ai bit di uno spostamento a destra su un numero negativo con segno è definito dall'implementazione e quindi non può essere garantito che sia portatile, ad esempio:

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

È anche indefinito se il numero di bit che desideri spostare è un numero negativo, ad esempio:

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

Il bit right shift non cambia il valore dei valori originali a meno che non sia specificatamente assegnato all'operatore di assegnazione bit saggio bit >>= :

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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow