El relleno se realiza para alinear ciertos tipos de datos, es decir, para asegurar que los datos de un tipo determinado tengan una dirección que sea un múltiplo de un número especificado. Esto varía entre los diferentes modelos de CPU, pero a menudo los enteros de 2 bytes se alinean con direcciones que son múltiplos de enteros de 2 y 4 bytes para direcciones que son múltiplos de 4. Normalmente, los caracteres no necesitan alinearse.
De modo que si solo hay un campo en una estructura, siempre que la estructura se coloque en una dirección con el límite adecuado, no hay necesidad de relleno. Y siempre lo será: el sistema siempre alinea los bloques con el límite más grande que alguna vez se requerirá, generalmente 4 bytes u 8 bytes. La única cosa en la estructura será en un límite apropiado. El problema solo aparece cuando tiene varios campos, ya que la longitud de un campo puede no dar como resultado que el siguiente campo esté en el límite apropiado. Entonces, en su ejemplo, tiene una char, que por supuesto toma 1 byte, y una int, que toma 4. Supongamos que la estructura se coloca en la dirección 0x1000. Luego, sin relleno, el carácter se colocará en 0x1000 y el int en 0x1001. Pero los int son más eficientes cuando se encuentran en límites de 4 bytes, por lo que el compilador agrega algunos bytes de pad para llevarlo al siguiente límite, 0x1004. Entonces ahora tiene char (1 byte), relleno (3 bytes), int (4 bytes), un total de 8 bytes.
No hay mucho que pueda hacer para mejorar la situación en este caso. Cada estructura se alineará con un límite de 4 u 8 bytes, de modo que cuando el mínimo sea de 5 bytes, siempre se redondeará al menos a 8 en la práctica. (El sizeof no mostrará el relleno entre las estructuras, solo dentro, pero la memoria aún se pierde.)
En otros casos, puede minimizar el número de bytes de la libreta reorganizando el orden de los campos. Como decir que tienes tres char y tres int. Si se declara la estructura como
struct {char a; int b; char c; int d; char e; int f;}
entonces el compilador añadirá 3 bytes después de que el primer carácter para alinear la primera int, y luego tres bytes más después de la segunda char a alinear el segundo int. Eso da char (1) + pad (3) + int (4) + char (1) + pad (3) + int (4) + char (1) + pad (3) + int (4) = 24.
Pero si por el contrario lo declaró:
struct {char a; char c; char e; int b; int d; int f;}
entonces se obtendría char (1) + char (1) + char (1) + pad (1) + int (4) + int (4) + int (4) = 16.
Hace años leí el consejo de poner siempre los elementos más grandes primero para minimizar el relleno, es decir, primero poner longs, luego ints, luego short, y luego chars.
Si está asignando miles o millones de estos, puede guardar mucha memoria con esta técnica. Si solo va a asignar uno o dos, no va a importar mucho.
I <3 ASCII ART! –
Hola, ¿qué tal el caso struct {int b; char a; } X; Aquí si consideramos que int comienza desde la ubicación de la memoria en múltiplo de 4 y char para stat más tarde. El relleno también se realiza en este caso. ¿Por qué se requiere un relleno aquí si todos los miembros de la información siguen las condiciones de contorno? – Laavaa
@AbhishekSrinath debido a las matrices. Si tiene 'X x [2]', el segundo elemento - 'x [1]' - debe estar alineado a 4 bytes porque su primer miembro es 'int', que debe estar alineado a 4 bytes. –