¿Cómo generalizar una estructura a un int con el operador de asignación?

Resuelto Zak asked hace 9 meses • 1 respuestas

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 enumclase.

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?

Zak avatar Feb 16 '24 07:02 Zak
Aceptado

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 xes 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));
paddy avatar Feb 16 '2024 00:02 paddy