Usar la máscara de bits en C++

Jinku Hu 12 octubre 2023
  1. Use struct para definir la máscara de bits e implementar el objeto de fecha en C++
  2. Usa struct y union para definir la máscara de bits e implementar el objeto de fecha en C++
  3. Usa std::bitset para definir la máscara de bits en C++
Usar la máscara de bits en C++

Este artículo demostrará múltiples métodos de cómo usar la máscara de bits en C++.

Use struct para definir la máscara de bits e implementar el objeto de fecha en C++

struct es una estructura de datos popular en C++. Además, es sólo ligeramente diferente de la class en comparación con el lenguaje C. En este caso, sólo necesitamos definir struct con varios miembros de datos, pero hay una nueva notación : utilizada después de cada nombre de variable y un número entero especificado. Como se muestra en el código de ejemplo, declaramos una struct con miembros de datos de tipo uint32_t, y la suma de los números de la derecha es 32. Esta construcción implica que la struct ocupa el tamaño de un solo tipo de datos uint32_t en la memoria y el usuario puede acceder a sus rangos de campo de bits(23:5:4) por separado.

Este método se utiliza principalmente para ahorrar la utilización de la memoria de las estructuras de datos que pueden ser exprimidas en struct similares. También es una de las formas comunes de acceder a datos más pequeños que un byte en el lenguaje de programación C++. Nótese que el primer miembro year sólo puede contener valores enteros hasta 223-1 y otros miembros siguen de manera similar.

#include <iostream>

using std::cout;
using std::endl;

struct {
  uint32_t year : 23;
  uint32_t day : 5;
  uint32_t month : 4;
} typedef Bitfield;

int main() {
  Bitfield date = {2020, 13, 12};

  cout << "sizeof Bitfield: " << sizeof(date) << " bytes\n";
  cout << "date: " << date.day << "/" << date.month << "/" << date.year << endl;

  return EXIT_SUCCESS;
}

Producción :

sizeof Bitfield: 4 bytes
date: 13/12/2020

Usa struct y union para definir la máscara de bits e implementar el objeto de fecha en C++

El método anterior es una forma suficiente y correcta de implementar la máscara de bits. Sin embargo, tiene una desventaja: el acceso y la asignación de valores a los miembros lleva relativamente más tiempo que las operaciones en los tipos incorporados. Esto puede resolverse implementando un objeto de tipo union que consiste en una struct y una única variable de tipo incorporado. Nótese que, struct es la disposición es la misma que construiríamos en el método anterior. En este caso, la diferencia es la variable uint32_t ydm que ocupa el mismo tamaño que la struct.

La idea es inicializar/asignar a los miembros de datos sus valores mucho más rápido. Es decir, construimos un entero con operaciones de bits que coinciden exactamente con la disposición de los bits cuando se almacenan en la struct y luego lo asignamos a un solo miembro uint32_t. Esto ahorra tiempo para acceder a los datos una vez en lugar de repetir la misma operación para cada uno de los tres miembros.

La aritmética de bits es relativamente sencilla; es decir, comenzamos con el valor del primer miembro en la struct, que es OR-ed con el resultado del siguiente miembro desplazado a la izquierda por el número de bits que ocupa el miembro anterior, y sigue de manera similar.

#include <iostream>

using std::cout;
using std::endl;

union BitfieldFast {
  struct {
    uint32_t year : 23;
    uint32_t day : 5;
    uint32_t month : 4;
  };
  uint32_t ydm;
};

int main() {
  BitfieldFast date_f{};
  date_f.ydm = 2020 | (13 << 23) | (12 << 28);

  cout << "sizeof BitfieldFast: " << sizeof(date_f) << " bytes\n";
  cout << "date: " << date_f.day << "/" << date_f.month << "/" << date_f.year
       << endl;

  return EXIT_SUCCESS;
}
sizeof BitfieldFast: 4 bytes
date: 13/12/2020

Usa std::bitset para definir la máscara de bits en C++

std::bitset es una característica estándar de la biblioteca que incluye la clase para almacenar los datos de la máscara binaria. bitset tiene múltiples funciones útiles de manipulación incorporadas, y la declaración es bastante fácil. Puede ser inicializado con un valor binario de string o con múltiples valores numéricos. Las operaciones de bits son métodos incorporados y pueden ser llamadas con operadores tradicionales que están sobrecargados. Fíjese que el método reset modifica permanentemente el bitset desde el que se llama.

#include <bitset>
#include <iostream>

using std::cout;
using std::endl;

int main() {
  std::bitset<16> bs1("1100100011110010");
  std::bitset<16> bs2(0xfff0);
  cout << "bs1        : " << bs1 << endl;
  cout << "bs2        : " << bs2 << endl;
  cout << "NOT bs1    : " << ~bs1 << endl;
  cout << "bs1 AND bs2: " << (bs1 & bs2) << endl;
  cout << "bs1 reset  : " << bs1.reset() << endl;

  return EXIT_SUCCESS;
}

Producción :

bs1        : 1100100011110010
bs2        : 1111111111110000
NOT bs1    : 0011011100001101
bs1 AND bs2: 1100100011110000
bs1 reset  : 0000000000000000
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook