Use o alinhamento e preenchimento da estrutura em C

Jinku Hu 12 outubro 2023
  1. Compreender os princípios básicos de alinhamento e preenchimento em C
  2. Use a técnica de reordenação de membros para economizar espaço em objetos em C
Use o alinhamento e preenchimento da estrutura em C

Este artigo irá explicar vários métodos de como usar o alinhamento e preenchimento struct em C.

Compreender os princípios básicos de alinhamento e preenchimento em C

Todos os objetos na memória são representados como os tipos de dados primários como: char, short, int, long, pointer etc. Esses tipos de dados têm seus tamanhos correspondentes na memória. Na maioria dos processadores de desktop de 64 bits contemporâneos, os tamanhos são 1 byte para um char, 2 bytes para um short, 4 bytes para um int, 8 bytes para um ponteiro e assim por diante. Observe que esses não são tamanhos garantidos (exceto para char), mas pode-se recuperar o tamanho do objeto usando o operador sizeof. Agora, alinhamento é o método que os compiladores empregam para colocar variáveis ​​na memória, o que implica que cada tipo de dado básico é armazenado no endereço divisível pelo tamanho correspondente.

Normalmente, o alinhamento é utilizado para acessar objetos de dados de forma mais rápida e eficiente. O alinhamento força a declaração contínua de diferentes tipos de dados para incluir algum espaçamento entre seus endereços. Ou seja, se declararmos uma estrutura st1 com um ponteiro e um char como mostrado no exemplo a seguir, ela ocupará 16 bytes no total. Lembre-se, porém, de que um único ponteiro ocupa 8 bytes e um char ocupa um byte, então alguém poderia pensar que a estrutura st1 deve ocupar 9 bytes. Mas se comporta como se todos os membros estivessem alinhados com o tamanho do maior membro (ou seja, 8 bytes). A estrutura st2 demonstra uma estrutura semelhante que ocupa a mesma quantidade de memória, exceto que tem um array de 7 membros 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);
}

Resultado:

sizeof st1 = 16
sizeof st2 = 16

Use a técnica de reordenação de membros para economizar espaço em objetos em C

O exemplo anterior demonstra que há algum desperdício de memória quando as estruturas incluem tipos diferentes e não preenchem os limites do alinhamento. No entanto, existem alguns casos em que pode ser possível reordenar os membros da estrutura e economizar espaço extra.

O próximo código de exemplo define a estrutura foo1 que possui o maior membro (char *) no meio e foo2 com o mesmo membro do primeiro. Os tamanhos desses dois objetos são diferentes - 24 bytes e 16 bytes. Isso tem a ver com a ordem dos membros de dados. Na estrutura foo1, p precisa ser alinhado no endereço que é divisível por 8, então o int e o short antes de ocupar 8 bytes no total e dois char * s depois de ocupar os 8 bytes também. Embora, se movermos p para o primeiro lugar, os membros seguintes serão espremidos nos 8 bytes e a regra de alinhamento também será satisfeita. Assim, o tamanho de foo2 totaliza 16 bytes e é chamado para ser empacotado como struct. Observe que o compilador gcc tem o especificador especial __atributo__ ((embalado)) que pode forçar até mesmo membros struct não ordenados a serem empacotados.

#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);
}

Resultado:

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

Artigo relacionado - C Struct