Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: huchoko en 15 Junio 2019, 07:17 am



Título: Probar si varios bits están "seteados"
Publicado por: huchoko en 15 Junio 2019, 07:17 am
Buenas, tal cual en el título, nececito probar si varios bits de una variable estan "seteados" osea valen 1 (como saben bit 0 o 1).
Puedo comprobar un solo bit con:
Código
  1. if (variableacomprobar & indexdelbit) {
  2.    /* etc... */
  3. }
  4.  
Pero como lo hago para varios a la vez?
Por ejemplo, tengo una varible con dos bits que quiero comprobar a la vez:
Bits 7 y 6: quiero comprobar si el uno (bit 7) y el cero (bit 6) valen 1 y viceversa. Osea:
Código:
|15...|7|6|5|4|3|2|1|0|
       | |
       1 0
     Ó
       0 1
Espero haberme explicado bien, cualquier confusión preguntenme por aclaración. :)


Título: Re: Probar si varios bits están "seteados"
Publicado por: @XSStringManolo en 15 Junio 2019, 08:27 am
Lo puedes hacer de mucha maneras.
Guardas los bit en una cadena. Te inventas otra cadena para comparar. Recorres ambas cadenas con un bucle for y las comparas.
Ejemplo:
Código
  1. string cadena1 = "10001011";
  2. string cadenaParaComprobar = "11111111";
  3.  
  4. for (int i = 0; i < cadena1.size(); ++i)
  5. {
  6.     if (cadena1[i] == cadenaParaComprobar[i])
  7.      {
  8.     cout << "El bit numero " << i << " esta set" <<endl;
  9.      }
  10. }

Puedes usar los operadores bitwise diseñhados para eso de 200 maneras distintas para hacer lo mismo. Se suelen usar para comparar los bits, sumarlos, restarlos, desplazarlos, etc.


Pd: Te pongo ejemplos de los operadores.
Citar
resultado = X & Y;
X= 00001111
Y= 00011000

El resultado será:
00001000

Citar
resultado = X | Y;
X= 00001111
Y= 00011000

El resultado será:
00011111

Citar
resultado = X ^ Y;
X= 00001111
Y= 00011000

El resultado será:
00010111

Citar
resultado = 1 << 1;

El resultado será:
00000010
Es decir, 2 en decimal.

Citar
resultado = 1 >> 1;

El resultado será:
00000000
0 en decimal. Hechó al uno fuera y no había bits para guardar su valor. Se perdió.


Título: Re: Probar si varios bits están "seteados"
Publicado por: Eternal Idol en 15 Junio 2019, 08:47 am
https://en.wikipedia.org/wiki/Bitwise_operation

Supongamos que te interesa comprobar el tercer y el octavo bit. Siendo mask1 0x4 (100b = 0x4) y mask2 0x80 (10000000b = 0x80 = 128).

Código
  1. if ( (var & mask1) && !(var & mask2) )
  2. ...
  3. else if ( !(var & mask1) && (var & mask2) )
  4. ...

O:
Código
  1. if ( (var & (mask1 | mask2)) == mask1)
  2. ...
  3. else if ( (var & (mask1 | mask2)) == mask2)
  4. ...

Se puede hacer de muchas maneras, con diferente grado de optimizacion.


Título: Re: Probar si varios bits están "seteados"
Publicado por: @XSStringManolo en 15 Junio 2019, 09:01 am
Es de una traducción al español que estoy haciendo del libro de Apress Learn C++ for game development.

Capitulo 18: La STL. bitset.

El bitset no es exactamente un contenedor, se parece mas a un tipo de dato de STL.
No es compatible con iteradores, bucles for basados en rango o algoritmos STL.
Se utiliza para seguir valores booleanos en un set combinado. El metodo tradicional
para conseguir el mismo resultado son las flags implementadas usando operadores
bitwise y shifts.

Una de las diferencias de bitset con respecto a los contenedores de la STL es que no
necesitas especificar un tipo para el bitset.

Especializando bitset:

#include <bitset>

using namespace std;

namespace
{
   const unsigned int NUMERO_DE_BITS = 5
}

using MiBitset = bitset<NUMERO_DE_BITS>;



Diferentes constructores para bitset:

MiBitset DefaultConstructor; //Inicializa todos los bits a 0.
MiBitset UnsignedLongConstructor{0x17}; //Valor literal
MiBitset StringConstructor{ string{ "11011"} };



Trabajando con bitsets.
Un biset proporciona metodos para realizar un buen numero de operaciones
diferentes. Estos pueden dividirse entre metodos que preguntan sobre el
estado actual del bitset, y metodos usados para alterar los bits.

cout << boolalpha;

cout << "Tamanho del bitset: " << StringConstructor.size() << endl;
cout << "Numero de bits asignados: " << StringConstructor.count() << endl;

cout << "Hay algun bit asignado? " << StringConstructor.any() << endl;
cout << "Estan todos los bit asignados? "<<StringConstructor.all() << endl;
cout << "No hay bits asignados? " << StringConstructor.none() << endl;

for (unsigned int i = 0; i < StringConstructor.size(); ++i)
{
   cout << "Bit " << i << " Valor: " << StringConstructor << endl;
   cout << "Bit " << i << " test: " << stringConstructor.test(i) << endl;
}

El metodo size retorna el valor que le pasamos en la plantilla. El metodo
count retorna el numero de bit a los que le asignamos true.



Hay tres metodos para alterar los valores almacenados en bitset:

StringConstructor.set(1, false);
StringConstructor.set(1);
StringConstructor.set();

StringConstructor.reset(0);
StringConstructor.reset();

StringConstructor.flip(4);  
StringConstructor.flip();


El primer ejemplo utiliza el index de un bit y el valor a asignarle a ese bit.
El segundo utiliza solo un index y asigna 1 al bit correspondiente.
El tercero asigna 1 a todos los bits en el set.
El metodo reset hace lo mismo pero en vez de unos, asigna ceros.
El metodo flip cambia los unos por ceros y los ceros por unos. En caso de
indicarle un index, solo cambiara el bit que se encuentre en ese index.


Título: Re: Probar si varios bits están "seteados"
Publicado por: RayR en 15 Junio 2019, 16:32 pm
Primero, aclarar, tú lo quieres es probar si varios bits están todos encendidos o ninguno, porque probarlos individualmente ya lo sabes hacer, ¿cierto?

La forma más simple sería (suponiendo que mascara1, mascara2, etc. contienen cada una 1 bit a probar):

Código
  1. if ((variable & mascara1) && (variable & mascara2) &&  ...
Pero si son muchos bits a probar quedaría una condición larguísima y tendrías demasiadas operaciones. Mejor preparar una máscara combinada y hacer algo así:

Código
  1. mascara = mascara1 | mascara2 | ...
  2.  
  3. // Todos on
  4. if ( (variable & mascara) == mascara)
  5. ...
  6. // Todos off
  7. if (!(variable & mascara))


Título: Re: Probar si varios bits están "seteados"
Publicado por: Loretz en 15 Junio 2019, 16:51 pm
Si lo que necesitas es saber si está activo el bit 6 o el 7, pero no ambos a la vez, y no te importa cual de los dos, siempre que sea uno y solo uno de ellos el que esté activo, podrías hacer:

[EDITO:]
Código:
   unsigned var = 182;         // 1011 0110
    unsigned mask6 = 0x40;      // 0100 0000
    unsigned mask7 = 0x80;      // 1000 0000

    bool res = (var & mask6 || var & mask7) && !(var & mask6 && var & mask7);

En C++ puedes usar std::bitset también, que es más fácil para todos.