Contents

Memory alignment

This note was inspired by a work of Samuele Giraudo (LIGM, Université Paris-Est Marne-la-Vallée)

http://igm.univ-mlv.fr/~giraudo/Enseignements/

Memory alignment

https://en.wikipedia.org/wiki/Data_structure_alignment

Memory alignment of a given data is the way this data is organized in the memory. For instance, an array of n elements of type T is organized as a continuous array of sizeof(T) * n bytes.

How does memory alignment work for variables of a structured type? Let’s find out 😊

Memory alignment within a structured type

Let’s consider the following declarations:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
typedef struct {
uint8_t  x;
uint8_t  y;
uint16_t z;
}A;
typedef struct {
uint8_t  x;
uint16_t z;
uint8_t  y;
}B;

A and B are two structured types based on the same fields. Only fields order matters. However,

1
printf("%lu %lu\n", sizeof(A), sizeof(B));

displays 4 6. A and B have diferrent size due to memory alignment…

Completion bytes

Completion bytes are inserted in order to make each field of a structured type beginning at an address multiple of its type. In our example, we know that each field of uint8_t (resp. uint16_t) must begin at an address multiple of 1 (resp. 2).

Manual access

Let a a variable of type A initialized by:

1
A a = {0x10, 0x20, 0x30};

We can access fields of this structure as follows:

1
2
3
4
5
6
7
8
9
uint8_t x, y;
uint16_t z;
void *p;
p = &a;
x = *((uint8_t *) p);  /* Equivalent a x = a.x; */
p += 1;
y = *((uint8_t *) p);  /* Equivalent a y = a.y; */
p += 1;
z = *((uint16_t *) p); /* Equivalent a z = a.z; */

Let b a variable of type B initialized by:

1
B b = {0x10, 0x20, 0x30};

We can access fields of this structure as follows:

1
2
3
4
5
6
7
8
9
uint8_t x, y;
uint16_t z;
void *p;
p = &a;
x = *((uint8_t *) p);  /* Equivalent a x = a.x; */
p += 2;
y = *((uint8_t *) p);  /* Equivalent a y = a.y; */
p += 2;
z = *((uint16_t *) p); /* Equivalent a z = a.z; */

-Wpadded option

The compiler flag -Wpadded gives a warning when a type needs completion bytes. For instance, with the structured type B defined by:

1
2
3
4
5
typedef struct {
uint8_t  x;
uint16_t z;
uint8_t  y;
} B;

The follwing warning appears in the terminal:

1
2
main.c:7:1: warning: padding struct size to alignment boundary [-Wpadded]
 } B;

Memory alignment — A summary

Memory alignment for variables of a structured type relies on several parameters such as:

  • Processor architecture on which the code has been compiled.
  • Compiler itself. Therefore, it is recommended to be aware that size of a structured type is not a trivial issue and depends of the context.