Home > OS >  Size of a struct
Size of a struct

Time:06-09

As my known, the size of the structure depends upon what compiler is used and the compiler may add padding for alignment requirements.

On a 64-bit system. I have test for 2 examples:

Example 1:

struct
{
    uint8 a;
    uint32 b;
    uint8 c;
}ABC;

size of(uint8 a) == 1 bytes   3 bytes padding
size of(uint32 b) == 4 bytes   0 padding
size of(uint8 c) == 1 bytes   3 padding

==> So, size of(ABC) = 12 bytes.

Example 2:

struct
{
    uint8 a;
    uint16 b;
    uint8 c;
}ABC;

size of(uint8 a) == 1 bytes   1 bytes padding
size of(uint16 b) == 2 bytes   0 padding
size of(uint8 c) == 1 bytes   3 padding

==> So, I assumed size of(ABC) = 8 bytes.

However, the compiler return size of(ABC) = 6 bytes.

Why does the size of(ABC) = 6 bytes in Example 2 instead of 8 bytes as my understanding?

CodePudding user response:

The compiler tries to align objects of structure types such a way that the data member with strictest alignment would be appropriately aligned.

In this structure declaration

struct
{
    uint8 a;
    uint16 b;
    uint8 c;
}ABC;

the data member with the strictest alignment is the data member b. Its address should be aligned by two bytes. So the data member a is padded by one byte. To make the address of an object of the structure to be aligned by 2 bytes the data member c is also padded with one byte.

CodePudding user response:

The compiler may add padding for alignment requirements. Note that this applies not only to padding between the fields of a struct, but also may apply to the end of the struct (so that arrays of the structure type will have each element properly aligned).

For example:

struct foo_t {
    int x;
    char c;
};

Even though the c field doesn't need padding, the struct will generally have a sizeof(struct foo_t) == 8 (on a 32-bit system - rather a system with a 32-bit int type) because there will need to be 3 bytes of padding after the c field.

Note that the padding might not be required by the system (like x86 or Cortex M3) but compilers might still add it for performance reasons.

CodePudding user response:

size of(uint8 c) == 1 bytes 3 padding`
==> So, I assumed size of(ABC) = 8 bytes.

There is no reason to add three bytes of padding. Because the alignment requirement of uint8 (presumably really uint8_t or equivalent) is one byte and the alignment requirement of uint16 (presumably really uint16_t or equivalent) is two bytes, the alignment requirement of the full structure is the maximum of those, two bytes. Having used one byte for uint8 a, a byte for padding to make uint16 b aligned, two bytes for uint16 b, and a byte for uint8 c, the size of the structure up to that point is five bytes. Then only one more byte is needed to make it a multiple of its alignment requirement, so the total is six bytes.

The rules typically used to layout a structure are:

  • Each member in the structure has some size s and some alignment requirement a.
  • The compiler starts with a size S set to zero and an alignment requirement A set to one (byte).
  • The compiler processes each member in the structure in order:
  1. Consider the member’s alignment requirement a. If S is not currently a multiple of a, then add just enough bytes to S so that it is a multiple of a. This determines where the member will go; it will go at offset S from the beginning of the structure (for the current value of S).
  2. Set A to the least common multiple1 of A and a.
  3. Add s to S, to set aside space for the member.
  • When the above process is done for each member, consider the structure’s alignment requirement A. If S is not currently a multiple of A, then add just enough to S so that it is a multiple of A.

The size of the structure is the value of S when the above is done.

Additionally:

  • If any member is an array, its size is the number of elements multiplied by the size of each element, and its alignment requirement is the alignment requirement of an element.
  • If any member is a structure, its size and alignment requirement are calculated as above.
  • If any member is a union, its size is the size of its largest member plus just enough to make it a multiple of the least common multiple1 of the alignments of all the members.

For elementary types (int, double, et cetera), the alignment requirements are implementation-defined and are usually largely determined by the hardware. On many processors, it is faster to load and store data when it has a certain alignment (usually when its address in memory is a multiple of its size). Beyond this, the rules above follow largely from logic; they put each member where it must be to satisfy alignment requirements without using more space than necessary.

Footnote

1 I have worded this for a general case as using the least common multiple of alignment requirements. However, since alignment requirements are always powers of two, the least common multiple of any set of alignment requirements is the largest of them.

  • Related