Pregunta

Tengo un fondo de C #. Estoy muy un novato en un lenguaje de bajo nivel como C.

En C #, la memoria de struct se presenta por el compilador por defecto. El compilador puede volver a ordenar los campos de datos o una almohadilla de bits adicionales entre los campos implícitamente. Por lo tanto, tenía que especificar algún atributo especial para anular este comportamiento para la disposición exacta.

AFAIK, C no reordena o align diseño de memoria de un struct por defecto. Sin embargo, he oído que hay una pequeña excepción de que es muy difícil de encontrar.

¿Cuál es el comportamiento de la capa de memoria de C? ¿Cuál debe ser re-ordenado / alineado y no?

¿Fue útil?

Solución

En C, se permite que el compilador de dictar algunos de alineación para cada tipo primitivo. Típicamente, la alineación es el tamaño del tipo. Pero es enteramente aplicación específica.

bytes de relleno se introducen por lo que cada objeto está alineado correctamente. No se permite reordenamiento.

Es posible que todos los implementos de forma remota moderna compilador #pragma pack que permite el control sobre el relleno y la deja al programador para cumplir con la ABI. (Es estrictamente no estándar, sin embargo.)

A partir de C99 §6.7.2.1:

12 Cada miembro no campo de bits de una estructura o unión objeto está alineado de una manera definida implementación- consignar en su tipo.

13 Dentro de una objeto de estructura, la no campo de bits miembros y las unidades en que campos de bits residir tener direcciones que aumentando en el orden en que se son declarados. Un puntero a una estructura objeto, adecuadamente convertidos, puntos para su miembro inicial (o si ese miembro es un campo de bits, a continuación, a la unidad en que reside), y viceversa. Puede haber acolchado no identificado dentro de una estructura del objeto, pero no en su principio.

Otros consejos

aplicación específica Es, pero en la práctica la regla (en ausencia de #pragma pack o similar) es:

    miembros
  • Struct se almacenan en el orden en que se declaran. (Esto es requerido por la norma C99, como se ha mencionado aquí antes.)
  • Si es necesario, se añade el relleno antes de cada miembro de estructura, para asegurar la alineación correcta.
  • Cada tipo primitivo T requiere una alineación de bytes sizeof(T).

Por lo tanto, dada la siguiente estructura:

struct ST
{
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};
  • ch1 está en la posición 0
  • un byte de relleno se inserta a align ...
  • s en el offset 2
  • ch2 es en el offset 4, inmediatamente después de s
  • 3 bytes de relleno se insertan a align ...
  • ll en el offset 8
  • i es en el offset 16, justo después de la Segunda
  • 4 bytes de relleno se añaden al final de modo que la estructura general es un múltiplo de 8 bytes. He comprobado esto en un sistema de 64 bits:. Sistemas de 32 bits pueden permitir estructuras tengan alineación de 4 bytes

Así es sizeof(ST) 24.

Se puede reducirse a 16 bytes por la reordenación de los miembros de acolchado evite:

struct ST
{
   long long ll; // @ 0
   int i;        // @ 8
   short s;      // @ 12
   char ch1;     // @ 14
   char ch2;     // @ 15
} ST;

Se puede empezar por leer la href="http://en.wikipedia.org/wiki/Data_structure_alignment" rel="nofollow noreferrer"> estructura de datos artículo alineación Wikipedia para obtener una mejor comprensión de alineación de datos.

Desde el Wikipedia artículo :

medios de alineación de datos poniendo los datos en una memoria compensado igual a un múltiplo del tamaño de la palabra, lo que aumenta el rendimiento del sistema debido a la forma en la memoria de la CPU mangos. Para alinear los datos, puede ser necesario insertar algunos bytes sin sentido entre el final de la última estructura de datos y el comienzo de la siguiente, que es la estructura de datos de relleno.

6.54.8 Estructura-embalaje pragmas del CCG documentación:

Para la compatibilidad con Microsoft compiladores de Windows, GCC soporta un conjunto de directivas #pragma que cambian el máximo de alineación de los miembros de estructuras (distintos de cero de ancho Campos de bits), los sindicatos, y las clases posteriormente definido. El valor n a continuación siempre que se requiere para ser una pequeña potencia de dos y especifica la nueva alineación en bytes.

  1. #pragma pack(n) simplemente establece la nueva alineación.
  2. #pragma pack() establece la alineación a la que estaba en efecto cuando comenzó la compilación (Véase opción de línea de comando también -fpack-estructura [=] Ver el Código de Opciones GEN).
  3. #pragma pack(push[,n]) empuja el ajuste de la alineación actual en una pila interna y luego opcionalmente establece la nueva alineación.
  4. #pragma pack(pop) restaura la configuración de alineación a la que se salvó en la parte superior de la pila interna (y quita que entrada de la pila). Tenga en cuenta que #pragma pack([n]) no influye en esta pila interna; por lo que es posible tener #pragma pack(push) seguido de #pragma pack(n) múltiple instancias y finalizado por un solo #pragma pack(pop).

Algunos objetivos, por ejemplo, i386 y PowerPC, apoyar la #pragma ms_struct que establece una estructura como la documentada __attribute__ ((ms_struct)).

  1. #pragma ms_struct on vueltas en el diseño de estructuras declaró.
  2. #pragma ms_struct off se apaga el diseño de estructuras declaró.
  3. #pragma ms_struct reset se remonta al diseño predeterminado.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top