ARM Pointer Alignment Requirements

Updated: 20190620

I stumbled upon this tidbit while reviewing the ARM online documentation on unaligned access. Upon review the information seems obvious, but I was not aware of the specific alignment rules.

I am quoting here directly from ARM's website. If you are debugging unaligned access issues, I recommend reading the full article.

This is an excerpt from How does the ARM Compiler support unaligned accesses? Any emphasis made below is mine.

As mentioned above, a pointer should contain an address with correct alignment for the type.

  • uint32_t* requires 4-byte alignment
  • uint16_t* requires 2-byte alignment
  • uint8_t* requires 1-byte alignment

For structures, the alignment is that of the most aligned member. The compiler will generate code on the assumption that a pointer is correctly aligned. It does not add code to perform run-time checks. A pointer may contain an incorrectly aligned address for a number of reasons. A common cause is casting:

uint8_t tmp; 
uint32_t_pMyPointer = (uint32_t_)(&tmp);

This code takes the address of an uint8_t variable, then casts that address as a uint32_t pointer. The compiler will still assume that pMyPointer is correctly aligned for a uint32_t pointer. The compiler might then generate code that results in an unaligned access unknowingly. This can be avoided using the __packed qualifier:

__packed uint32_t* pMyPointer = (__packed uint32_t*)(&tmp);

Change Log

  • 20190620
    • Fixed broken link to ARM documentation (Thanks Jpn for pointing it out)