Operadores bitwise: ¿Cuál es la diferencia ^ = vs & = ~ (smthg)?

0

Estoy codificando para microcontroladores y he encontrado dos estilos de operaciones bitwise que me confunden bastante porque se usan indistintamente. Primero asumamos que nuestro REGISTRO tiene 4 bits; Bit 0,1,2,3. El valor predeterminado de REGISTRO al reiniciar es 1100.

1. ¿Cuál es la diferencia entre:

REGESTER ^= (1<<3) | (1<<2);

&

REGESTER &= ~( (1<<3) | (1<<2) );

2.¿Es el primero correcto? (No estoy seguro de que sea correcto)

3. Si el primero es correcto, ¿por qué utilizar la segunda declaración ya que el valor resultante es el mismo que el segundo?

Resultado final: 0000

    
pregunta Killerbee89

3 respuestas

2

Estos no son intercambiables en general. Obtendrá los mismos resultados en este caso particular, porque el primero alterna los bits 3 y 2, el segundo los borra. Cuál es el correcto depende de lo que quieras lograr

    
respondido por el user28910
5
  1. ^= x es XOR. Cambia el estado de los bits.

    &= ~x es AND NOT. Se borran los bits.

  2. ^= x solo es correcto si alternar los bits es lo que desea hacer cada vez que se ejecuta este código. Esto podría ser correcto si quisiera encender un LED, por ejemplo, pero no debería usarse si quiere asegurarse de que el registro termine en un estado específico.

respondido por el duskwuff
2

Además de las respuestas ya publicadas y la comprensión de lo que hacen estos operadores, es igualmente importante entender qué tan peligrosos son los operadores de bitwise.

Estás utilizando literales enteros como 1 , un literal que es de tipo (con signo) int . Los operadores firmados son peligrosos de usar junto con los operadores bitwise.

Muchos operadores como | , ^ y ~ no se preocupan por el tipo de operandos, trabajan en el nivel binario sin formato. Pero los operadores de cambio pueden invocar varias formas desagradables de errores de comportamiento indefinido, en caso de cambiar un operando firmado. Por ejemplo, el código 1 << 31 invoca un comportamiento indefinido, ya que cambia los datos a los bits de signo. De manera similar, los cambios a la derecha de las variables firmadas tienen un comportamiento definido por la implementación si el operando es negativo.

Para empeorar las cosas, hay promociones enteras implícitas. Código como este también invoca un comportamiento indefinido:

unsigned char byte = 1;
byte = ~byte << 1;

Porque es lo mismo que 0xFFFF FFFE << 1 . Aquí puede pasar cualquier cosa, incluido un bloqueo del programa.

Del mismo modo, un código como este se comportará inesperadamente:

uint8_t mask = 0xF0;
uint8_t data = 0x01;
if(data > ~mask)
{
  puts("0x01 is larger than 0x0F");
}

Lo que esto significa en la práctica es que cosas como las mencionadas leyes de De Morgan no se aplican de manera transparente al código C. Las promociones de tipo implícito y el comportamiento mal especificado pueden causar estragos.

La solución es evitar los tipos firmados en los sistemas integrados y escribir código lo más libre posible de promociones implícitas.

Más información: Reglas de promoción de tipo implícito .

    
respondido por el Lundin

Lea otras preguntas en las etiquetas