2

To understand more about padding I created this structure. Why is the output of state 0x1413 and not 0x1615. I am expecting compiler will pad 3 bytes after zip and should give output as 0x1615.

typedef struct
{
    uint8_t zip; // I am assuming 3 bytes will be padded after this.
    uint16_t state[2]; // 4 bytes
    uint32_t country; //4 bytes
} address;

int main()
{
    uint8_t buf[] = {0x11, 0x12, 0x13, 0X14, 0x15, 0x16,0x17, 0x18, 0x09, 0x0A, 0x0B, 0x0C, 0X0D, 0x0E, 0x0F};
    address *val;
    val = (address*)buf;
    printf("size of address %lu \n",sizeof(address));
    printf("zip 0x%0x \n",val->zip);
    printf("state0 0x%0x state1 0x%0x \n",val->state[0],val->state[1]);
    printf("country 0x%0x \n",val->country);
}

Output is:

./a.out
size of address 12 
zip 0x11 
state0 0x1413 state1 0x1615 
user968000
  • 1,765
  • 3
  • 22
  • 31
  • [You must use `%zu` to print the result of `sizeof`](https://stackoverflow.com/q/940087/995714) – phuclv Sep 18 '19 at 14:12
  • 1
    Why would you expect three bytes of padding between `zip` and `state`? `zip` is a `uint8_t`, so it is only one byte and should not need additional alignment. `state` is an array of `uint16_t`, which is two bytes, so, if it needs alignment, two-byte alignment is usually sufficient. (Alignment depends on the platform or C implementation.) To get two-byte alignment, you only need one byte of padding, not three. – Eric Postpischil Sep 18 '19 at 14:18
  • 3
    When doing experiments like this, do not create an array of `uint8_t` like `buf` and then reinterpret it as a `struct` using `(address *) buf`. Instead, create a `struct`, as with the definition `address X;`, and then use `memcpy(&X, buf, sizeof X);` to get the bytes into it. Writing the bytes into an existing structure this way is supported by the C standard. Reinterpreting possibly misaligned bytes of a buffer like `buf` as a `struct` is not supported by the C standard. (Another supported method is to put both the `address` struct and the `buf` array as members in a union.) – Eric Postpischil Sep 18 '19 at 14:20
  • Side comment: Are you asking because (a) you're curious or (b) you've been tasked with writing a structure definition which matches an externally-imposed storage layout or (c) you've gotten the impression that struct padding is a generally important thing to know about? If (a), fine. If (b), you have my sympathies -- this is a popular but (IMO) misguided exercise. Finally, if (c), maybe just don't worry about it! IMO, padding is *not* generally important to know about. I've been programming in C for ~40 years, and in all the work I've done, it has almost never been important. – Steve Summit Sep 18 '19 at 14:25

1 Answers1

5

Padding is typically based on the base type of each of its members.

The member state is an array of uint16_t, so this field is aligned on a 2 byte boundary even though the entire array is 4 bytes. What's important is that each member of the array is correctly aligned. So there is 1 byte of padding after zip to align state and state starts at offset 2.

After that the next available offset is 6 so two more padding bytes are needed for country to be aligned on a 4 byte boundary. So then the offset of country is 8.

So now the structure looks like this:

typedef struct
{
    uint8_t zip;         // offset 0
    // 1 byte padding
    uint16_t state[2];   // offset 2
    // 2 bytes padding
    uint32_t country;    // offset 8
} address;

For more details on how padding is usually implemented, see this guide.

dbush
  • 205,898
  • 23
  • 218
  • 273