dsell002
dsell002

Reputation: 1306

Is it safe to use struct members as references to memory offsets?

On the ARM Information Center site, they had this suggestion for using structs to map variables to memory addresses.

#define PORTBASE 0x40000000

typedef struct Port
{
    uint32_t reg0;
    uint32_t reg1;
    uint32_t reg2;
} Port;

volatile struct Port * const reg_p = (struct Port *)PORTBASE;

However, I have seen someone else suggest that compilers can add padding between members of a struct object and the only way to ensure this doesn't happen is to use the packed attribute, as in GCC __attribute__((__packed__)), for example.

It seems to me that padding would only be introduced by the compiler to align member boundaries, but I don't see in the C99 standard that it explicitly states this shouldn't happen in other cases. In fact, it seems like it says it could happen.

From C99 section 6.7.2.1,

12

Each non-bit-field member of a structure or union object is aligned in an implementationdefined manner appropriate to its type.

13

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

15

There may be unnamed padding at the end of a structure or union.

Given the above example, is it guaranteed that reg1 will be exactly 32-bits offset from reg0 without telling the compiler not to add padding?

Upvotes: 3

Views: 271

Answers (1)

user2859193
user2859193

Reputation: 434

The padding between the members is added, so that Values are aligned to 32Bit(depends on architecture) e.g. a uint32_t should start at an aligned offset 4*2^x to be faster accessible as a normal 32bit Pointer can be used, as you struct consists only of 32Bit values this is automatically true, if PORTBASE is an Aligned address.

Therefore the Compiler should in this case not add padding, but you can always add

__attribute__((__packed__))

to be sure.

The Compiler would add padding in cases like:

struct
{
    uint8_t  a;
    uint32_t b;
}

where b would end up on an unaligned address.

The problem is that for arm you might get Compilers that are not completely C99 compatible.

Upvotes: 1

Related Questions