vocabulario sintaxis sentencias nomenclatura estructuras dev aprendiendo c++ struct

sintaxis - Relleno de estructura en C++



sintaxis de c++ pdf (5)

Si tengo una struct en C ++, ¿no hay forma de leerla / escribirla con seguridad en un archivo compatible con multiplataforma / compilador?

Porque si lo entiendo correctamente, cada compilador ''almohadillas'' de manera diferente en función de la plataforma de destino.


Larga historia corta, no. No existe una manera independiente de la plataforma, conforme a los estándares para lidiar con el relleno.

El relleno se llama "alineación" en el Estándar, y comienza a discutirlo en 3.9 / 5:

Los tipos de objetos tienen requisitos de alineación (3.9.1, 3.9.2). La alineación de un tipo de objeto completo es un valor entero definido por la implementación que representa un número de bytes; un objeto se asigna a una dirección que cumple los requisitos de alineación de su tipo de objeto.

Pero continúa desde allí y termina en muchos rincones oscuros del Estándar. La alineación es "definida por la implementación", lo que significa que puede ser diferente en diferentes compiladores, o incluso a través de modelos de direcciones (es decir, 32 bits / 64 bits) bajo el mismo compilador.

A menos que tenga requisitos de rendimiento realmente duros, puede considerar almacenar sus datos en un disco en un formato diferente, como cadenas de caracteres. Muchos protocolos de alto rendimiento envían todo usando cadenas cuando el formato natural puede ser otra cosa. Por ejemplo, una fuente de intercambio de baja latencia en la que trabajé recientemente envía fechas como cadenas con el formato siguiente: "20110321" y los tiempos se envían de manera similar: "141055.200". A pesar de que este feed de intercambio envía 5 millones de mensajes por segundo durante todo el día, todavía usan cadenas para todo porque de esa manera pueden evitar el endian-ness y otros problemas.


No, eso no es posible. Es debido a la falta de estandarización de C ++ en el nivel binario .

Don Box escribe (citando de su libro Essential COM , capítulo COM As A Better C ++ )

C ++ y portabilidad


Una vez que se toma la decisión de distribuir una clase de C ++ como una DLL, uno se enfrenta con una de las debilidades fundamentales de C ++ , es decir, la falta de estandarización a nivel binario . Aunque el documento de trabajo borrador ISO / ANSI C ++ intenta codificar qué programas compilarán y cuáles serán los efectos semánticos de ejecutarlos, no intenta estandarizar el modelo de tiempo de ejecución binario de C ++ . La primera vez que se hará evidente este problema es cuando un cliente intenta vincularse con la biblioteca de importación de la DLL de FastString desde un entorno de desarrollo de C ++ que no sea el utilizado para compilar la DLL de FastString.

El relleno de Struct se hace de forma diferente por diferentes compiladores. Incluso si usa el mismo compilador, la alineación del empaque para las estructuras puede ser diferente según el paquete de pragma que esté utilizando.

No solo eso, si escribes dos estructuras cuyos miembros son exactamente iguales, la única diferencia es que el orden en el que se declaran es diferente, entonces el tamaño de cada estructura puede ser (y a menudo es) diferente.

Por ejemplo, mira esto,

struct A { char c; char d; int i; }; struct B { char c; int i; char d; }; int main() { cout << sizeof(A) << endl; cout << sizeof(B) << endl; }

Compila con gcc-4.3.4 , y obtienes esta salida:

8 12

Es decir, los tamaños son diferentes a pesar de que ambas estructuras tienen los mismos miembros.

Código en Ideone: http://ideone.com/HGGVl

La conclusión es que el estándar no habla sobre cómo se debe realizar el relleno, por lo que los compiladores son libres de tomar cualquier decisión y no se puede suponer que todos los compiladores toman la misma decisión.


No, no hay una manera segura. Además del relleno, tienes que ocuparte de diferentes órdenes de bytes y diferentes tamaños de tipos integrados.

Debe definir un formato de archivo y convertir su estructura a dicho formato. Las bibliotecas de serialización (p. Ej., Boost :: serialization, o los intérpretes de protocolos de google) pueden ayudar con esto.


Podría usar algo como boost::serialization .


Si tiene la oportunidad de diseñar la estructura usted mismo, debería ser posible. La idea básica es que debe diseñarlo de modo que no haya necesidad de insertar bytes de relleno en él. el segundo truco es que debes manejar las diferencias en endianess.

Describiré cómo construir la estructura usando escalares, pero debería poder usar estructuras anidadas, siempre que aplique el mismo diseño para cada estructura incluida.

Primero, un hecho básico en C y C ++ es que la alineación de un tipo no puede exceder el tamaño del tipo. Si fuera así, entonces no sería posible asignar memoria usando malloc(N*sizeof(the_type)) .

Diseña la estructura, empezando por los tipos más grandes.

struct { uint64_t alpha; uint32_t beta; uint32_t gamma; uint8_t delta;

A continuación, rellene la estructura manualmente, para que al final coincida con el tipo más grande:

uint8_t pad8[3]; // Match uint32_t uint32_t pad32; // Even number of uint32_t }

El siguiente paso es decidir si la estructura debe almacenarse en formato endian pequeño o grande. La mejor manera es "intercambiar" todo el elemento in situ antes de escribir o después de leer la estructura, si el formato de almacenamiento no coincide con la endialencia del sistema host.