¿Por qué se agrega relleno, si char viene después de int?

5 minutos de lectura

Por ejemplo, hay una estructura

struct A
{
char a;
int i;
};

En este caso, tenemos un[1 byte] + relleno[3 byte] + int[4 byte] = 8.

Ahora hagamos una pequeña actualización en la estructura anterior,

struct A
{
int i;
char a;
};

En este caso, char viene después de int y no es necesario agregar bytes de relleno, lo que significa sizeof(A) = 5 bytes, pero en este caso también obtengo el resultado de 8 bytes. Por qué ?

Ok, y que tal este caso

struct s
   {
       int b;
       double c;
       char a;
   };

De acuerdo con la lógica dada a continuación, hay un: size = b[4 bytes] + padding[4 bytes] + c[8] + a[1] + padding[7 bytes to align with double] = 24pero después de la ejecución obtengo 16. ¿Cómo es esto posible?

¿Por que se agrega relleno si char viene despues de
trucos

En este caso char viene después int y no es necesario agregar bytes de relleno, significa sizeof(A) = 5 byte, pero en este caso también obtengo el 8 resultado de byte. Por qué ?

Primero debe comprender por qué se necesita relleno.
wiki dice que:

La alineación de la estructura de datos es la forma en que se organizan y se accede a los datos en la memoria de la computadora. Consta de dos cuestiones separadas pero relacionadas: alineación de datos y relleno de estructura de datos. Cuando una computadora moderna lee o escribe en una dirección de memoria, lo hará en fragmentos del tamaño de una palabra (por ejemplo, fragmentos de 4 bytes en un sistema de 32 bits) o más grandes. La alineación de datos significa colocar los datos en un desplazamiento de memoria igual a un múltiplo del tamaño de la palabra, lo que aumenta el rendimiento del sistema debido a la forma en que la CPU maneja la memoria.. 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 el relleno de la estructura de datos.

Para hacer el tamaño múltiplo de 4 (alineación de int), el segundo fragmento se rellenará con 3 bytes Después de la compilación, el segundo fragmento se rellenará para una alineación adecuada como

struct A
{
    int i;
    char a; 
    char Padding[3]; // 3 bytes to make total size of the structure 8 bytes
};    

EDITAR: Recuerde siempre estas dos reglas de oro del relleno de estructura:

  • El relleno solo se inserta cuando un miembro de la estructura está seguido por un miembro con un alineación más grande requisito o en el final de la estructura
  • El último miembro se rellena con el número de bytes necesarios para que el tamaño total de la estructura sea un múltiplo de la alineación más grande de cualquier miembro de la estructura.

En caso de

struct s
{
    int b;
    double c;
    char a;
};  

la alineación se llevará a cabo como

struct s
{
    int b;             // 4 bytes. b is followed by a member with larger alignment.
    char Padding1[4];  // 4 bytes of padding is needed 
    double c;          // 8 bytes
    char d;            // 1 byte. Last member of struct. 
    char Padding2[7];  // 7 bytes to make total size of the structure 24 bytes 
};   

También tenga en cuenta que al cambiar el orden de los miembros en una estructura, es posible cambiar la cantidad de relleno necesario para mantener la alineación. Esto se puede hacer si los miembros se ordenan por requisitos de alineación descendente.

struct s
{ 
    double c;   // 8 bytes
    int b;      // 4 bytes 
    char a;     // 1 byte. Only last member will be padded to give structure of size 16 
};   

  • Pero, ¿es correcto que el doble pueda comenzar con un desplazamiento que es un múltiplo de 8? En su explicación, el desplazamiento del doble es igual a 5.

    usuario1886376

    8 de marzo de 2015 a las 16:13

  • @usuario2846015; ¿Cuál será el tamaño de struct s { double c; int b; char a; }; ?

    – trucos

    8 de marzo de 2015 a las 16:28

  • en este orden será c[8] + segundo[4] + un[1] + relleno[3 to align with double] = 16

    usuario1886376

    08/03/2015 a las 16:31

  • @usuario2846015; ¿Por qué? ¿no debería 24?

    – trucos

    8 de marzo de 2015 a las 16:32

  • @usuario2846015; Esperar. Actualizando mi respuesta.

    – trucos

    08/03/2015 a las 17:00

La razón por la que el compilador tiene que agregar relleno al final de su estructura es que la estructura puede ser parte de una matriz, y cada elemento de una matriz debe estar alineado correctamente.

Parece que su plataforma quiere que un int se alinee a 4 bytes.

Si declaras una matriz de tus struct A:

struct A array[2];

entonces el primero int miembro de array[1] también debe tener una alineación de 4 bytes. Así que el compilador rellena su struct A ser de 8 bytes para lograr eso, mientras que si no agregara ningún relleno y sizeof(struct A) eran 5 bytes, array[1] no estaría correctamente alineado.

(Tenga en cuenta que un compilador no puede insertar relleno entre los elementos de la matriz, el relleno debe ser parte de los elementos de la matriz, ya que sizeof array debe ser el mismo que sizeof(struct A) * 2 en el caso anterior)

No sólo cada miembro de la struct tiene que estar alineado con los datos, pero el struct tiene que alinearse con el tamaño del miembro más grande en el struct. Entonces, se agrega relleno a struct A tal que su tamaño debe ser un múltiplo del mayor de sizeof i y sizeof a.

Eche un vistazo a las preguntas frecuentes de C aquí

Si uno va a tener una matriz de estructuras, todos los elementos dentro de la matriz deben tener el mismo tamaño y alineación; esto implicaría que para las cosas en una matriz, el tamaño debe ser un múltiplo de la alineación. La única vez que sería útil tener una estructura cuyo tamaño no fuera un múltiplo de la alineación sería si no se incorporara directamente a otra matriz, sino que se usara como parte de otra estructura. Ese tipo de situación ocurre a veces, pero no lo suficiente como para merecer una atención especial en el diseño del lenguaje.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad