Utilice estructura de alineación y relleno en C

Jinku Hu 12 octubre 2023
  1. Comprender los conceptos básicos de alineación y relleno en C
  2. Utilice la técnica de reordenación de miembros para ahorrar espacio en objetos en C
Utilice estructura de alineación y relleno en C

Este artículo explicará varios métodos de cómo utilizar la alineación y el relleno de struct en C.

Comprender los conceptos básicos de alineación y relleno en C

Todos los objetos en la memoria se representan como los tipos de datos primarios como: char, short, int, long, pointer, etc. Estos tipos de datos tienen su tamaño correspondiente en la memoria. En la mayoría de los procesadores de escritorio de 64 bits actuales, los tamaños son 1 byte para un char, 2 bytes para un short, 4 bytes para un int, 8 bytes para un puntero, y así sucesivamente. Tenga en cuenta que estos no son tamaños garantizados (excepto para char), pero se puede recuperar el tamaño del objeto utilizando el operador sizeof. Ahora, la alineación es el método que emplean los compiladores para colocar variables en la memoria, lo que implica que cada tipo de datos básico se almacena en la dirección divisible por el tamaño correspondiente.

Por lo general, la alineación se utiliza para acceder a los objetos de datos de forma más rápida y eficiente. La alineación obliga a declarar continuamente diferentes tipos de datos para incluir algún espacio entre sus direcciones. Es decir, si declaramos una estructura st1 con un puntero y un char como se muestra en el siguiente ejemplo, ocupará 16 bytes en total. Sin embargo, tenga en cuenta que un solo puntero toma 8 bytes y un char toma un byte, por lo que uno pensaría que la estructura st1 debe ocupar 9 bytes. Pero se comporta como si todos los miembros estuvieran alineados con el tamaño de miembro más grande (es decir, 8 bytes). La estructura st2 demuestra una estructura similar que ocupa la misma cantidad de memoria, excepto que tiene un array de 7 miembros char.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[]) {
  typedef struct {
    char *p;
    char c2;
  } st1;

  typedef struct {
    char *p;
    char c2;
    char padding[7];
  } st2;

  printf("sizeof st1 = %zu\n", sizeof(st1));
  printf("sizeof st2 = %zu\n", sizeof(st2));

  exit(EXIT_SUCCESS);
}

Producción :

sizeof st1 = 16
sizeof st2 = 16

Utilice la técnica de reordenación de miembros para ahorrar espacio en objetos en C

El ejemplo anterior demuestra que hay un desperdicio de memoria cuando las estructuras incluyen diferentes tipos y no llenan los límites de alineación. Sin embargo, hay algunos casos en los que es posible reordenar los miembros de la estructura y ahorrar espacio adicional.

El siguiente código de ejemplo define la estructura foo1 que tiene el miembro más grande (char *) en el medio y foo2 con el mismo miembro que el primero. Los tamaños de estos dos objetos son diferentes: 24 bytes y 16 bytes. Esto tiene que ver con el orden de los miembros de datos. En la estructura foo1, p debe alinearse en la dirección que es divisible por 8, por lo que int y short antes de ocupar 8 bytes en total y dos char * s después de ocupar los 8 bytes también. Aunque, si movemos p al primer lugar, los siguientes miembros se comprimirán en los 8 bytes y la regla de alineación también se cumplirá. Por lo tanto, el tamaño de foo2 totaliza 16 bytes y es llamado para ser empaquetado como struct. Tenga en cuenta que el compilador gcc tiene el especificador especial __attribute__ ((packed)) que puede forzar a empaquetarse incluso miembros de struct no ordenados.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[]) {
  typedef struct {
    int n1;
    short s1;
    char *p;
    char c1;
    char c2;
  } foo1;

  typedef struct {
    char *p;
    int n1;
    short s1;
    char c1;
    char c2;
  } foo2;

  typedef struct {
    int n1;
    short s1;
    char *p;
    char c1;
    char c2;
  } __attribute__((packed)) foo3;

  printf("sizeof foo1 = %zu\n", sizeof(foo1));
  printf("sizeof foo2 = %zu\n", sizeof(foo2));
  printf("sizeof foo3 = %zu\n", sizeof(foo3));

  exit(EXIT_SUCCESS);
}

Producción :

sizeof foo1 = 24
sizeof foo2 = 16
sizeof foo3 = 16
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artículo relacionado - C Struct