Quiero capturar parte de los datos dentro de algunas estructuras C para serializarlos/deserializarlos parcialmente, escribiendo los bytes de la memoria en el disco, y viceversa.sizeof() parte de una estructura C - tipo de
Las estructuras no se conocen de antemano, se construyen dinámicamente con mi propio generador de código C (así como el código que lo serializará). Los campos serializables se colocarán al comienzo de la estructura.
Digamos que una tiene una estructura con 4 campos, y los dos primeros son para ser serializado:
typedef struct {
int8_t x1;
int32_t x2; /* 1 + 4 = 5 bytes (if packed) */
int8_t y1;
int32_t y2; /* 1 + 4 +1 + 4 = 10 bytes (if packed) */
} st;
planeo para agarrar el puntero a la variable de estructura y escribir/leer los n
bytes que cubren los dos primeros campos (x1, x2
). No creo que deba preocuparme por la alineación/empaque porque no pretendo que la serialización sobreviva a diferentes compilaciones (solo se espera que un ejecutable único lea/escriba los datos). Y, como me estoy enfocando en una amplia gama de compiladores-arquitecturas, no quiero poner suposiciones sobre el alineamiento-embalaje o trucos específicos del compilador.
Entonces, necesito contar los bytes. Y no puedo simplemente hacer sizeof(st.x1)+sizeof(st.x2)
debido a alingment-padding. Por lo tanto, tengo la intención de restar puntos, desde el principio de la estructura al primer campo "no persistente":
st myst;
int partsize = (char*)&myst.y1 - (char*)(&myst);
printf("partial size=%d (total size=%d)\n",partsize,sizeof(myst));
Esto parece funcionar. Y puede colocarse en una macro.
(Para el registro: intenté también escribir otra macro que no requiera una instancia de la estructura, algo así como this, pero no parece posible aquí, pero esto no me importa demasiado).
Mi pregunta: ¿Es esto correcto y seguro? ¿Puedes ver alguna trampa potencial, o algún mejor enfoque?
Entre otras cosas: ¿El estándar C (y los compiladores de facto) asumen que los campos de estructuras se encuentran en la memoria en el mismo orden en que están definidos en la fuente? Esto probablemente es una pregunta estúpida, pero yo quiero estar seguro ...
ACTUALIZACIÓN: Algunas conclusiones de las respuestas y mis propias conclusiones:
No parece haber ningún problema con mi enfoque . En particular, C dicta que los campos de estructura nunca cambiarán el orden.
Uno también podría (según lo sugerido por un aswer) contar desde el último campo persistente y agregar su tamaño:
(char*)&myst.x2 + sizeof(&myst.x2) - (char*)(&myst)
. Eso sería equivalente, excepto que incluiría no los bytes de relleno (si están presentes) para el último campo. Una ventaja muy pequeña, y una desventaja muy pequeña, en ser menos simple.Pero la respuesta aceptada, con
offsetof
, parece ser preferible a mi propuesta. Es claro, expresivo y puro tiempo de compilación, no requiere una instancia de la estructura. Además, parece ser estándar, disponible en cualquier compilador. Si uno no necesita una construcción en tiempo de compilación, y tiene una instancia de la estructura disponible (como es mi caso), ambas soluciones son esencialmente equivalentes.
Pregunta relacionada: http://stackoverflow.com/questions/2748995/c-struct-memory-layout – payne
Quité la etiqueta C++, ya que no hay C++ en algún lugar cerca de esta pregunta. – Puppy