Representação de tipos estruturados (cont)

Estruturas heterogêneas: structs

O layout de structs na memória depende da questão de alinhamento. Cada campo da estrutura que corresponde a uma palavra deve necessariamente começar em um endereço múltiplo de 4. Assim, se tivermos uma declaração como:

struct s{
  char c[2];
  float b;
};

onde um campo ocupando dois bytes precede um campo que corresponde a uma palavra, o compilador terá que deixar dois bytes não utilizados entre o array de caracteres e o float.

struct s s1;
memória alocada para s1:
    início de s1
    ----------------------------------------------------------------------
    |s1.c[0]|s1.c[1]| xxxxx | xxxxx | s1.b  | s1.b   | s1.b    | s1.b    |
    ----------------------------------------------------------------------

Os bytes não usados na memória alocada a um struct são chamados de padding.

Observe que o início de cada estrutura tem que ser sempre alinhado, senão não saberemos quantos bytes devem ser "pulados" para chegar a um endereço múltiplo de 4. Isso é especialmente relevante na hora em que montamos um array de structs, já que os elementos de um array são alocados contiguamente na memória.

O tamanho total da struct tem que já ser calculado para o caso da struct ser usada dentro de um array e respeitar a regra de cálculo do tamanho total do array, usando sizeof (sizeof(array)=num_elem*sizeof(elem)). Por isso, o padding pode às vezes ocorrer no final. Por exemplo, a declaração:

struct s {
  float b;
  char c[2];
}; 
indica que o campo b deve estar sempre alinhado em um múltiplo de 4 bytes. Como a estrutura pode vir a ser usada em um array, o compilador irá automaticamente colocar um padding de 2 bytes ao final da estrutura, ou seja, o sizeof de s será 8.

Para a declaração:

struct s bobo[2];
a alocação de memória ficaria:
                              --------------------
    início de bobo  --->      | bobo[0].b        |
                              --------------------
                              | bobo[0].b        |
                              --------------------
                              | bobo[0].b        |
                              --------------------
                              | bobo[0].b        |
                              --------------------
                              | bobo[0].c[0]     |
                              --------------------
                              | bobo[0].c[1]     |
                              --------------------
                              |     XXX          |
                              --------------------
                              |     XXX          |
                              --------------------
                              | bobo[1].b        |
                              --------------------
                              | bobo[1].b        |
                              --------------------
                              | bobo[1].b        |
                              --------------------
                              | bobo[1].b        |
                              --------------------
                              | bobo[1].c[0]     |
                              --------------------
                              | bobo[1].c[1]     |
                              --------------------
                              |     XXX          |
                              --------------------
                              |     XXX          |
                              --------------------

Outros exemplos:

Referência

Representação de números inteiros negativos

Complemento a 2

ex 3 bits

binário		comp. a 2
000		0
001		1
010		2
011		3
100		-4 *
101		-3
110		-2
111		-1

Limites

extensão de representação

Operadores Relacionais

Soma e Subtração

Overflow

Referência: