¿Cómo declarar el relleno en una estructura?

Tengo una estructura en la memoria, pero aún no se conocen todos los miembros (esta estructura tiene ingeniería inversa). Lo que quiero hacer es tener la representación en la memoria como:

struct Name {
    long Id;
    byte unknown[32];
    float X;
};

Pero quiero el byte unknown[32] ser invisible, así que cuando estoy usando algo del tipo Name Solo puedo ver las 2 variables Id y X. Creo que es similar a:

struct Name {
    long Id;
    byte : 32*8; // So this doesn't appear
    float X;
};

Pero esto no funciona 1. porque estoy limitado a 8 bytes por línea, por lo que debería verse así:

struct Name {
    long Id;
    long long : 64;
    long long : 64;
    long long : 64;
    long long : 64;
    float X;
};

Y en segundo lugar, cuando trato de hacer esto, no funciona como se esperaba (el acceso a X no se refiere al desplazamiento 0x24 de la estructura).

preguntado el 22 de mayo de 12 a las 17:05

¿Por qué no puedes usar la primera forma y hacer unknown private? -

Es probable que la respuesta sea específica del compilador. ¿Qué compilador usas? -

@Steve: hablando con pedantería, el diseño de los miembros de datos con diferentes especificadores de acceso no está especificado (C++03 9.2 y 11.1). Simplemente viviría con nombres públicos que obviamente están destinados a no ser utilizados. -

El último enfoque no funciona porque la alineación de long long no es lo mismo que char. -

Me habría ido con el nombre, pero como una clase de plantilla no puedes hacer nada con: ideone.com/o8JQm -

2 Respuestas

Estás en el camino correcto, pero simplemente tienes los detalles equivocados. El compilador insertó relleno de alineación en su versión de Name. Este programa podría hacer lo que quieras:

#include <cstddef>
#include <iostream>
#include <cassert>

struct Name {
    long Id;  // offset 0x00
    int : 32; // offset 0x04
    long long : 64;  // 0x08
    long long : 64;  // 0x10
    long long : 64;  // 0x18
    int : 32; // offset 0x20
    float X;  // offset 0x24
};

int main () {
  assert(sizeof(int) == 4);
  assert(sizeof(long) == 4);
  assert(sizeof(float) == 4);
  assert(sizeof(long long) == 8);
  assert(offsetof(Name, Id) == 0);
  assert(offsetof(Name, X) == 0x24);
}

Alternativamente, puede investigar #pragma pack.

Nota:: No existe una solución portátil y sancionada por estándares para su problema. Los compiladores son libres de insertar bytes de relleno (casi) donde y como quieran. Pero puede haber soluciones aprobadas por el compilador que no sean portátiles, como las dos anteriores.

contestado el 22 de mayo de 12 a las 19:05

Si está buscando una solución genérica para cualquier estructura desconocida, eche un vistazo a este código

template <size_t SIZE> class UnknownStruct
{
public:
    enum {size = SIZE};
    explicit UnknownStruct(unsigned char* data)
    {
        memcpy(m_data, data, SIZE);
    }
    template <size_t OFFSET, typename TYPE> TYPE* read()
    {
        if(OFFSET + sizeof(TYPE) <= SIZE)
            return reinterpret_cast<TYPE*>(m_data + OFFSET);
        return NULL;
    }
private:
    unsigned char m_data[SIZE];
};

UnknownStructure es un blob de bytes sin procesar (de TAMAÑO de conteo) al que puede acceder con el read función. Aquí hay un ejemplo de cómo usarlo para su problema

class Name : public UnknownStruct<sizeof(long) + 32 + sizeof(float)>
{
public:
    explicit Name(unsigned char* data) : UnknownStruct<size>(data){}
    long& ID()
    {
        return *read<0, long>();
    }
    float& X()
    {
        return *read<sizeof(long) + 32, float>();
    }
};

el código de llamada se vería así

unsigned char foodata[100] = {0};
Name fooreader(foodata);
fooreader.ID() = 57;
long id = fooreader.ID();

a medida que descubra más sobre la estructura, puede agregar más funciones a la clase Nombre que leerá los tipos de las compensaciones apropiadas

La ventaja de este código es que puede usarse para cualquier estructura desconocida. Puede haber otras bibliotecas que proporcionen esta solución, pero esta es lo suficientemente corta y simple de usar

contestado el 22 de mayo de 12 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.