¿Cómo generalizar una estructura a un int con el operador de asignación?
Estoy intentando usar una estructura para empaquetar varios enteros más pequeños en un archivo uint32_t
.
struct PackedData {
PackedData & operator=(uint32_t x) {
a = (x >> 24) & 0xFF;
b = (x >> 8) & 0xFFFF;
c = x & 0xFF;
return *this;
}
uint32_t operator=(PackedData x) {
uint32_t temp;
temp = (x.a << 24) & 0xFF000000;
temp |= (x.b << 8) & 0xFFFF00;
temp |= x.c & 0xFF;
return temp;
}
uint32_t a : 8;
uint32_t b : 16;
uint32_t c : 8;
};
Originalmente, esperaba heredar de a uint32_t
, similar a lo que puedes hacer con una enum
clase.
struct PackedData : uint32_t {
Desafortunadamente eso no se compila.
Lo extraño es que la estructura que pegué se compila y ni siquiera genera advertencias con -Wall -Wextra --pedantic
.
En el lado positivo, puedo ver que mi estructura tiene 4 bytes y puedo asignar un entero de 32 bits a la estructura. Sin embargo, no puedo asignar la estructura a un entero de 32 bits.
Estoy seguro de que la sintaxis del siguiente método es completamente incorrecta, pero no sé cómo y el compilador no me ayuda.
uint32_t operator=(PackedData x) {
uint32_t temp;
temp = (x.a << 24) & 0xFF000000;
temp |= (x.b << 8) & 0xFFFF00;
temp |= x.c & 0xFF;
return temp;
}
¿Puede esta idea funcionar o hay una manera mejor?
Puede definir un operador de conversión implícito de la siguiente manera:
struct PackedData {
// ...
operator uint32_t () const {
return (a << 24) | (b << 8) | c;
}
};
Ahora puedes hacer:
PackedData p { 0xef, 0x1234, 0xab };
uint32_t x = p;
El valor de x
es 0xef1234ab
.
Tenga en cuenta que el enmascaramiento al convertir desde campos de bits no es necesario. El compilador ya se encarga de eso internamente.
Si es muy importante que su estructura tenga siempre el tamaño correcto debido a suposiciones en otras partes de un proyecto más grande, generalmente es una buena idea agregar una aserción estática. El lugar más apropiado para hacerlo suele ser siguiendo la definición de clase:
struct PackedData {
// ...
};
static_assert(sizeof(PackedData) == sizeof(uint32_t));