in

c ++ – ¿Cómo se configura, borra y alterna un solo bit?

apple touch icon@2
/*
**  Bit set, clear, and test operations
**
**  public domain snippet by Bob Stout
*/

typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

OK, analicemos las cosas …

La expresión común con la que parece tener problemas en todos estos es «(1L << (posn))". Todo esto hace es crear una máscara con un solo bit y que funcionará con cualquier tipo de entero. El argumento "posn" especifica la posición en la que desea el bit. Si posn == 0, esta expresión se evaluará como:

0000 0000 0000 0000 0000 0000 0000 0001 binary.

Si posn == 8, se evaluará a:

0000 0000 0000 0000 0000 0001 0000 0000 binary.

En otras palabras, simplemente crea un campo de ceros con un 1 en la posición especificada. La única parte complicada está en la macro BitClr () donde necesitamos establecer un solo bit 0 en un campo de unos. Esto se logra usando el complemento a 1 de la misma expresión indicada por el operador tilde (~).

Una vez que se crea la máscara, se aplica al argumento tal como sugiere, mediante el uso de los operadores bit a bit y (&), o (|) y xor (^). Dado que la máscara es de tipo long, las macros funcionarán igual de bien en char’s, short’s, int’s o long’s.

La conclusión es que esta es una solución general para toda una clase de problemas. Por supuesto, es posible e incluso apropiado reescribir el equivalente de cualquiera de estas macros con valores de máscara explícitos cada vez que lo necesite, pero ¿por qué hacerlo? Recuerde, la sustitución de macros ocurre en el preprocesador, por lo que el código generado reflejará el hecho de que los valores son considerados constantes por el compilador, es decir, es tan eficiente usar las macros generalizadas como «reinventar la rueda» cada vez que necesite hacer manipulación de bits.

¿No estás convencido? Aquí hay un código de prueba: utilicé Watcom C con optimización completa y sin usar _cdecl, por lo que el desmontaje resultante sería lo más limpio posible:

—-[ TEST.C ]————————————————– ————–

#define BOOL(x) (!(!(x)))

#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))

int bitmanip(int word)
{
      word = BitSet(word, 2);
      word = BitSet(word, 7);
      word = BitClr(word, 3);
      word = BitFlp(word, 9);
      return word;
}

—-[ TEST.OUT (disassembled) ]———————————————–

Module: C:BINKtst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS

Segment: _TEXT  BYTE   00000008 bytes  
 0000  0c 84             bitmanip_       or      al,84H    ; set bits 2 and 7
 0002  80 f4 02                          xor     ah,02H    ; flip bit 9 of EAX (bit 1 of AH)
 0005  24 f7                             and     al,0f7H
 0007  c3                                ret     

No disassembly errors

—-[ finis ]————————————————– —————

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Perl – Fecha y hora

qhQy5SGS8TEV8NmQjZ4uyS 1200 80

10 mejores lectores de cómics para Android e iOS