580 votos

¿Por qué no se sizeof para una estructura igual a la suma de sizeof de cada miembro?

¿Por qué el operador sizeof 'devolvió una talla más grande para una estructura que los tamaños totales de los miembros de la estructura?

563voto

Kevin Puntos 7334

Esto es debido a la estructura de la alineación. Estructura de la alineación se refiere a la posibilidad de que el compilador insertar la memoria no utilizada en una estructura para que los miembros de datos están perfectamente alineados para un mejor rendimiento. Muchos procesadores realizan mejor cuando fundamental tipos de datos se almacenan en bytes de las direcciones que son múltiplos de sus tamaños.

He aquí un ejemplo usando la configuración típica para un procesador x86:

struct X
{
    short s; /* 2 bytes */
             /* 2 padding bytes */
    int   i; /* 4 bytes */
    char  c; /* 1 byte */
             /* 3 padding bytes */
};

struct Y
{
    int   i; /* 4 bytes */
    char  c; /* 1 byte */
             /* 1 padding byte */
    short s; /* 2 bytes */
};

struct Z
{
    int   i; /* 4 bytes */
    short s; /* 2 bytes */
    char  c; /* 1 byte */
             /* 1 padding byte */
};

const int sizeX = sizeof(X); /* = 12 */
const int sizeY = sizeof(Y); /* = 8 */
const int sizeZ = sizeof(Z); /* = 8 */

Uno puede minimizar el tamaño de las estructuras por poner el más grande de tipos de datos en el principio de la estructura y el más pequeño de tipos de datos al final de la estructura (estructura Z en el ejemplo anterior).

NOTA IMPORTANTE: Tanto el C y C++ estándares del estado que la estructura de la alineación es definido por la implementación. Por lo tanto, cada compilador puede elegir la alineación de datos de manera diferente, lo que resulta en diferentes e incompatibles de plantillas de datos. Por esta razón, cuando se trata de las bibliotecas que serán utilizados por los distintos compiladores, es importante entender cómo los compiladores de la alineación de datos. Algunos compiladores han de línea de comandos de configuración y/o especiales, #pragma instrucciones para cambiar la estructura de los valores de alineación.

153voto

EmmEff Puntos 1789

Embalaje y byte alineación ... describe en la C FAQ aquí

23voto

INS Puntos 5679

Si desea que la estructura para tener un cierto tamaño con GCC, por ejemplo, usar __attribute__((packed)).

En Windows, puede establecer la alineación de uno de bytes cuando se utiliza el cl.exe compier con el /Zp opción.

Generalmente es más fácil para que la CPU de datos de access, que es un múltiplo de 4 (u 8), en función de la plataforma y también en el compilador.

Así que es cuestión de alineación, básicamente.

Usted necesita tener buenas razones para cambiar.

13voto

Kyle Burton Puntos 10471

Esto puede ser debido a la alineación de bytes y el relleno, de modo que la estructura salga un número par de bytes (o palabras) en su plataforma. Por ejemplo, en C en Linux, los 3 siguientes estructuras:

#include "stdio.h"


struct oneInt {
  int x;
};

struct twoInts {
  int x;
  int y;
};

struct someBits {
  int x:2;
  int y:6;
};


int main (int argc, char** argv) {
  printf("oneInt=%zu\n",sizeof(struct oneInt));
  printf("twoInts=%zu\n",sizeof(struct twoInts));
  printf("someBits=%zu\n",sizeof(struct someBits));
  return 0;
}

Tienen miembros que el tamaño (en bytes) de 4 bytes (32 bits), 8 bytes (2x 32 bits) y de 1 byte (2+6 bits), respectivamente. El programa anterior (en Linux usando gcc) imprime los tamaños de 4, 8, y 4 - donde la última estructura se rellena de modo que es una sola palabra (4 x 8 bytes en mi plataforma de 32 bits).

oneInt=4
twoInts=8
someBits=4

12voto

Nishant Puntos 1605
Predict the output of following program.

#include <stdio.h>

// Alignment requirements
// (typical 32 bit machine)

// char         1 byte
// short int    2 bytes
// int          4 bytes
// double       8 bytes

// structure A
typedef struct structa_tag
{
   char        c;
   short int   s;
} structa_t;

// structure B
typedef struct structb_tag
{
   short int   s;
   char        c;
   int         i;
} structb_t;

// structure C
typedef struct structc_tag
{
   char        c;
   double      d;
   int         s;
} structc_t;

// structure D
typedef struct structd_tag
{
   double      d;
   int         s;
   char        c;
} structd_t;

int main()
{
   printf("sizeof(structa_t) = %d\n", sizeof(structa_t));
   printf("sizeof(structb_t) = %d\n", sizeof(structb_t));
   printf("sizeof(structc_t) = %d\n", sizeof(structc_t));
   printf("sizeof(structd_t) = %d\n", sizeof(structd_t));

   return 0;
}

La Alineación De Los Datos:

Cada tipo de datos en C/C++ se han requisito de alineación (de hecho, es el mandato de la arquitectura del procesador, no por el idioma). Un procesador tendrá el procesamiento de la longitud de la palabra como la de bus de datos de tamaño. En un equipo de 32 bits, el procesamiento de tamaño de palabra de 4 bytes.

enter image description here

Históricamente la memoria de byte direccionable y organizados secuencialmente. Si la memoria está organizada como único banco de un byte de ancho, el procesador número 4 de la memoria de lectura ciclos para obtener un número entero. Es más económico para leer todos los 4 bytes de un entero en un ciclo de memoria. Para tomar esta ventaja, la memoria se organizan como grupo de 4 bancos, como se muestra en la figura de arriba.

Las direcciones de memoria todavía ser secuenciales. Si el banco 0, ocupa una dirección X, banco 1, 2 y banco 3 va a ser en (X + 1), (X + 2) (X + 3) direcciones. Si un entero de 4 bytes se asigna a X dirección X es múltiplo de 4), el procesador necesita sólo una memoria ciclo de leer todo entero.

enter image description here

De datos de una variable alineación se refiere a la forma de los datos almacenados en estos bancos. Por ejemplo, la alineación natural de la int de 32 bits de la máquina es de 4 bytes. Cuando un tipo de datos es, naturalmente, alineados, la CPU obtiene en ciclos de lectura mínima.

Del mismo modo, la alineación natural de short int es de 2 bytes. Es decir, un short int puede ser almacenado en el banco 0 banco 1 par o banco 2 banco 3 par. Un doble requiere de 8 bytes, y ocupa dos filas en los bancos de memoria. La desalineación de las dos de la fuerza de más de dos leer ciclos de captura de datos doble.

Tenga en cuenta que una variable double será asignado en 8 bytes límite en equipo de 32 bits y requiere de dos memoria de lectura ciclos. En una máquina de 64 bits, basado en el número de bancos, doble variable será asignado en 8 bytes límite y sólo requiere de un ciclo de lectura de memoria.

Estructura Relleno:

En C/C++ una de las estructuras se utilizan como paquete de datos. No proporcionan ningún dato de la encapsulación de datos o de ocultación de las características de C++ caso es una excepción debido a su semejanza semántica con clases).

La salida del Programa Anterior:

Por el bien de la conveniencia de asumir cada tipo de estructura variable se almacena en 4 bytes límite (es decir 0×0000), es decir. la dirección base de la estructura es múltiplo de 4 (necesidad no es necesario siempre, véase la explicación de los structc_t).

estructura de Un

El structa_t primer elemento es de tipo char, que es un byte alineados, seguido por cortos int. short int es de 2 bytes alineado. Si el short int elemento es asignado inmediatamente después de que el char elemento, comenzará en una dirección impar límite. El compilador inserta un byte de relleno después de que el char para garantizar short int tendrá una dirección múltiplo de 2 (es decir. 2 bytes alineado). El tamaño total de structa_t será sizeof(char) + 1 (relleno) + sizeof(short), 1 + 1 + 2 = 4 bytes.

structure B

El primer miembro de structb_t es short int seguido por char. Desde char puede ser en cualquier byte límite sin relleno necesario entre short int y char, en total que ocupa 3 bytes. El siguiente miembro es de tipo int. Si el int se asigna de inmediato, se iniciará en una extraña byte de la frontera. Tenemos 1 byte de relleno después de que el char miembros para hacer de la dirección de la próxima int miembro es de 4 bytes alineado. En total, el structb_t requiere 2 + 1 + 1 (relleno) + 4 = 8 bytes.

structure C – Every structure will also have alignment requirements

Aplicar el mismo análisis, structc_t necesidades sizeof(char) + 7 bytes de relleno + sizeof(double) + sizeof(int) = 1 + 7 + 8 + 4 = 20 bytes. Sin embargo, la sizeof(structc_t) será de 24 bytes. Es porque, junto con los miembros de la estructura, de la estructura de las variables de tipo también tendrá la alineación natural. Vamos a entender esto con un ejemplo. Decir, hemos declarado un array de structc_t como se muestra a continuación

structc_t structc_array[3];

Asumir la dirección de la base de structc_array es 0×0000 para facilitar los cálculos. Si el structc_t ocupa 20 (0×14) bytes como hemos calculado, la segunda structc_t elemento de la matriz (indexada en 1) será en 0×0000 + 0×0014 = 0×0014. Es la dirección de inicio de índice 1 elemento de la matriz. El doble de los miembros de este structc_t será asignado en 0×0014 + 0×1 + 0×7 = 0x001C (28 decimal), que no es múltiplo de 8 y en conflicto con los requisitos de alineación de la doble. Como hemos mencionado en la parte superior, la alineación de la exigencia de la doble es de 8 bytes.

Para evitar tales problemas de desalineación, compilador introducir el requisito de alineación a cada estructura. Será como la del miembro más grande de la estructura. En nuestro caso la alineación de structa_t es de 2, structb_t es de 4 y structc_t es de 8. Si necesitamos estructuras anidadas, el tamaño de la más grande estructura interna será la alineación de inmediato estructura más grande.

En structc_t del programa anterior, habrá de relleno de 4 bytes después de int miembro para hacer que el tamaño de la estructura múltiple de su alineación. Así, la sizeof (structc_t) es de 24 bytes. Se garantiza la correcta alineación incluso en las matrices. Usted puede verificar.

structure D - How to Reduce Padding?

Por ahora, está claro que el relleno es inevitable. Hay una manera de minimizar el relleno. El programador debe declarar los miembros de la estructura en el aumento/disminución de la orden de tamaño. Un ejemplo es structd_t dado en nuestro código, cuyo tamaño es de 16 bytes en lugar de 24 bytes de structc_t.

Debido a la alineación de los requerimientos de los diferentes tipos de datos, cada miembro de la estructura debe ser naturalmente alineado. Los miembros de la estructura asignados secuencialmente en orden creciente. Vamos a analizar cada struct declaró en el programa anterior.

Donde, si el entero es asignado a una dirección que no sea múltiplo de 4, se extiende a través de dos filas de los bancos, como se muestra en la figura de arriba. Un entero requiere de dos ciclo de lectura de memoria para recuperar los datos.

Referencia: http://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X