Tamaño de estructura y variable correspondiente.

Si defino una variable char

char a; 

y una estructura con un solo miembro char

 struct OneChar { char a; }; 

¿Tendrán estas dos definiciones el tamaño de ‘char’ en todos los comstackdores? Mi duda es, si definimos una variable char en la estructura, debido al empaquetamiento de memoria, ¿tomará más tamaño que tamaño de char?

Depende de la architecture y del comstackdor. Para este caso en particular, debe estar seguro, pero revise el Relleno de la estructura de datos .

Aquí hay un extracto :

Alineación típica de estructuras C en x86

Los miembros de la estructura de datos se almacenan secuencialmente en una memoria, de modo que en la estructura debajo del miembro Data1 siempre precederá a Data2 y Data2 siempre precederá a Data3:

 struct MyData { short Data1; short Data2; short Data3; }; 

Si el tipo “corto” se almacena en dos bytes de memoria, entonces cada miembro de la estructura de datos que se muestra arriba se alineará con 2 bytes. Data1 estaría en el offset 0, Data2 en el offset 2 y Data3 en el offset 4. El tamaño de esta estructura sería de 6 bytes.

El tipo de cada miembro de la estructura generalmente tiene una alineación predeterminada, lo que significa que, a menos que el progtwigdor lo solicite, se alineará en un límite predeterminado. Las siguientes alineaciones típicas son válidas para comstackdores de Microsoft, Borland y GNU al comstackr para x86 de 32 bits:

  • Un char (un byte) se alineará con 1 byte.
  • Un corto (dos bytes) se alineará con 2 bytes.
  • Un int (cuatro bytes) se alineará con 4 bytes.
  • Un flotador (cuatro bytes) se alineará con 4 bytes.
  • Un doble (ocho bytes) se alineará con 8 bytes en Windows y con 4 bytes en Linux.

Aquí hay una estructura con miembros de varios tipos, con un total de 8 bytes antes de la comstackción:

 struct MixedData { char Data1; short Data2; int Data3; char Data4; }; 

Después de la comstackción, la estructura de datos se complementará con bytes de relleno para garantizar una alineación adecuada para cada uno de sus miembros:

 struct MixedData /* after comstacktion */ { char Data1; char Padding0[1]; /* For the following 'short' to be aligned on a 2 byte boundary */ short Data2; int Data3; char Data4; char Padding1[3]; }; 

El tamaño comstackdo de la estructura es ahora de 12 bytes. Es importante tener en cuenta que el último miembro se rellena con el número de bytes necesarios para ajustarse al tipo más grande de la estructura. En este caso, se agregan 3 bytes al último miembro para rellenar la estructura al tamaño de una palabra larga.

Es posible cambiar la alineación de las estructuras para reducir la memoria que requieren (o para ajustarse a un formato existente) cambiando la alineación del comstackdor (o “empaquetado”) de los miembros de la estructura.

Si solicita que la estructura MixedData de arriba se alinee con un límite de un byte, el comstackdor descartará la alineación predeterminada de los miembros y no se insertarán bytes de relleno.

Si bien no hay una forma estándar de definir la alineación de los miembros de la estructura, algunos comstackdores usan las directivas #pragma para especificar el empaquetado dentro de los archivos de origen. Aquí hay un ejemplo:

 #pragma pack(push) /* push current alignment to stack */ #pragma pack(1) /* set alignment to 1 byte boundary */ struct MyPackedData { char Data1; long Data2; char Data3; }; #pragma pack(pop) /* restre original alignment from stack */ 

Esta estructura tendría un tamaño comstackdo de 6 bytes. Las directivas anteriores están disponibles en comstackdores de Microsoft, Borland, GNU y muchos otros.

Mientras haya un solo miembro, creo que estás a salvo con la suposición.

El caso que usted lista se empaquetará como una estructura de 1 byte en todos los ABI que conozco.

Pero si necesita manejar casos más complicados, la mejor práctica es usar siempre sizeof(struct OneChar) al calcular los tamaños de memoria y tomar el desplazamiento de la dirección de campo cuando necesita calcular las direcciones a través de un truco como:

 (char*)&(((struct OneChar*)0)->a) - (char*)0 

Todos los s tendrán el mismo tamaño, sin importar si están solos o dentro de una estructura.

Lo que puede suceder dentro de una estructura es que hay relleno entre los miembros … pero eso también puede suceder en las variables “independientes”.

Cuando tomas el tamaño de una estructura, incluye los bytes de relleno. Pero, si tienes algo como lo siguiente:

 void fun() { char c; int n; } 

El comstackdor es libre de insertar el relleno por cualquier razón que vea. Por lo tanto, el relleno podría estar allí en caso de variables independientes, simplemente no se puede saber sobre eso como en el caso de una estructura.

Varios comstackdores se optimizarán para agregar relleno entre o al final de la estructura. Por lo tanto, no es seguro en todos los comstackdores o plataformas asumir que el tamaño asignado es lo que parece. Verifique las opciones de su comstackdor para configurar la estructura de relleno.

Por ejemplo, Visual Studio usa la directiva #pragma pack para anular las optimizaciones predeterminadas.