Buscar..


Observaciones

Las operaciones de cambio de bits no son portátiles en todas las arquitecturas de procesadores, diferentes procesadores pueden tener diferentes anchos de bits. En otras palabras, si escribiste

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

Este valor sería diferente en una máquina de 64 bits en comparación con una máquina de 32 bits, o de un procesador basado en x86 a un procesador basado en PIC.

No es necesario tener en cuenta la endiancia para las operaciones de bits en sí mismas, es decir, el desplazamiento a la derecha ( >> ) desplazará los bits hacia el bit menos significativo y un XOR realizará una exclusiva o en los bits. Endian-ness solo se debe tener en cuenta con los datos en sí, es decir, si endian-ness es una preocupación para su aplicación, es una preocupación independientemente de las operaciones de bits.

& - a nivel de bit y

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;

Salida

a = 6, b = 10, c = 2

Por qué

Un poco inteligente AND opera en el nivel de bits y utiliza la siguiente tabla de verdad booleana:

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

Cuando el valor binario para a ( 0110 ) y el valor binario para b ( 1010 ) son AND 'ed juntos, obtenemos el valor binario de 0010 :

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

El bit AND AND no cambia el valor de los valores originales a menos que esté específicamente asignado para usar el operador compuesto de asignación bit a bit &= :

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

| - en modo bit o

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;

Salida

a = 5, b = 12, c = 13

Por qué

Un poco inteligente OR opera en el nivel de bits y utiliza la siguiente tabla de verdad booleana:

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

Cuando el valor binario para a ( 0101 ) y el valor binario para b ( 1100 ) se unen con OR , obtenemos el valor binario de 1101 :

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

El OR de bits no cambia el valor de los valores originales a menos que se asigne específicamente para usar el operador compuesto de asignación de bits |= :

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

^ - XOR bitwise (OR exclusivo)

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;

Salida

a = 5, b = 9, c = 12

Por qué

Un poco inteligente XOR (exclusivo o) opera en el nivel de bits y utiliza la siguiente tabla de verdad booleana:

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

Observe que con una operación XOR true OR true = false donde con las operaciones true AND/OR true = true , de ahí la naturaleza exclusiva de la operación XOR.

Usando esto, cuando el valor binario para a ( 0101 ) y el valor binario para b ( 1001 ) son XOR 'ed juntos obtenemos el valor binario de 1100 :

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

El XOR de bits no cambia el valor de los valores originales a menos que se asigne específicamente para usar el operador compuesto de asignación de bits ^= :

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

El XOR de bits se puede utilizar de muchas maneras y se utiliza a menudo en operaciones de máscara de bits para el cifrado y la compresión.

Nota: el siguiente ejemplo se muestra a menudo como un ejemplo de un buen truco. Pero no se debe utilizar en el código de producción (hay mejores formas en que std::swap() para lograr el mismo resultado).

También puede utilizar una operación XOR para intercambiar dos variables sin un temporal:

int a = 42;
int b = 64;

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

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

Para lograr esto, debe agregar un cheque para asegurarse de que pueda usarse.

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

Entonces, aunque parece un buen truco por sí solo, no es útil en código real. xor no es una operación lógica básica, sino una combinación de otras: a ^ c = ~ (a & c) & (a | c)

también en el 2015+ las variables de los compiladores se pueden asignar como binarias:

int cn=0b0111;

~ - bitwise NOT (complemento único)

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;

Salida

a = 234, b = 21

Por qué

Un bit sabio NOT (complemento único) opera en el nivel de bits y simplemente voltea cada bit. Si es un 1 , se cambia a un 0 , si es un 0 , se cambia a un 1 . El bit NO tiene el mismo efecto que XOR'ing un valor contra el valor máximo para un tipo específico:

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

El bit bit NOT NO también puede ser una forma conveniente de verificar el valor máximo para un tipo integral específico:

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

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

El bit NOT no cambia el valor del valor original y no tiene un operador de asignación compuesto, por lo que no puede hacer a ~= 10 por ejemplo.

El bit NOT NOT ( ~ ) no debe confundirse con el NOT lógico ( ! ); donde un bit sabio NO volteará cada bit, un lógico NO usará todo el valor para realizar su operación, en otras palabras (!1) != (~1)

<< - desplazamiento a la izquierda

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

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

Salida

a = 1, b = 2

Por qué

El desplazamiento en el bit a la izquierda desplazará los bits del valor de la mano izquierda ( a ) el número especificado a la derecha ( 1 ), esencialmente rellenando los bits menos significativos con 0, de modo que se desplaza el valor de 5 (binario 0000 0101 ) hacia la izquierda 4 veces (por ejemplo, 5 << 4 ) producirá el valor de 80 (binario 0101 0000 ). Es posible que tenga en cuenta que desplazar un valor a la izquierda 1 vez también equivale a multiplicar el valor por 2, por ejemplo:

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

Pero debe tenerse en cuenta que la operación de desplazamiento a la izquierda desplazará todos los bits a la izquierda, incluido el bit de signo, por ejemplo:

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;

Salida posible: a = 2147483647, b = -2

Si bien algunos compiladores producirán resultados que parecen esperados, se debe tener en cuenta que si deja un número con signo para cambiar de manera que el bit de signo se vea afectado, el resultado no está definido . Tampoco está definido si el número de bits que desea desplazar es un número negativo o es mayor que el número de bits que puede contener el tipo de la izquierda, por ejemplo:

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

El desplazamiento a la izquierda de bits no cambia el valor de los valores originales a menos que se asigne específicamente para usar el operador compuesto de asignación de bits <<= :

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

>> - cambio a la derecha

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

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

Salida

a = 2, b = 1

Por qué

El cambio de bit a la derecha desplazará los bits del valor de la mano izquierda ( a ) el número especificado a la derecha ( 1 ); debe tenerse en cuenta que, si bien la operación de un cambio a la derecha es estándar, lo que sucede con los bits de un cambio a la derecha en un número negativo con signo está definido por la implementación y, por lo tanto, no se puede garantizar que sea portátil, por ejemplo:

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

Tampoco está definido si el número de bits que desea desplazar es un número negativo, por ejemplo:

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

El desplazamiento a la derecha de los bits no cambia el valor de los valores originales a menos que se asigne específicamente el uso del operador compuesto de asignación de bits >>= :

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


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow