2
votes
typedef struct structc_tag
{
   char        c;
   double      d;
   int         s;
} structc_t;

I read in a blog that this will take 24 bytes of data:

sizeof(char) + 7 byte padding + sizeof(double) + sizeof(int) + 4 byte padding = 1 + 7 + 8 + 4 + 4 = 24 bytes.

My question is why the 7 byte padding, why can't we use 3bytes of padding there and utilise next 8 bytes for double? And what is the need for last 4 bytes?

2
double entities should be aligned to addresses divisible by 8, otherwise the FPU might become unhappy while trying to load the value from memory. A very slow unaligned load must be issued in such cases (and some platforms do not support unaligned access at all). This is especially true in 64-bit mode on x64 CPUs where math is done primarily using SSE. Last four bytes are there to guarantee correct alignment when stacking many such structures one after another (e.g. in an array of struct_t).Hristo Iliev
It's usually very hard to know exactly how large a struct or object is going to be in real implementation, as it changes on each platform you're using. You should usually just rely on the compiler to do the best it can with the required fields and pad as necessary for best performance. This is why people use sizeof() when checking the number of bytes an object uses -- even for primitives like int.Pyrce
if you may, just order the fields according to their size, in your case this would probably help on most platformsJens Gustedt

2 Answers

3
votes

You need to consider what the happens if you allocate an array of these structures with malloc():

structc_t *p = malloc(2 * sizeof *p);

Consider a platform where sizeof(double) == 8, sizeof(int) == 4 and the required alignment of double is 8. malloc() always returns an address correctly aligned for storing any C type - so in this case a will be 8 byte aligned. The padding requirements then naturally fall out:

  • In order for a[0].d to be 8-byte aligned, there must therefore be 7 bytes of padding after a[0].c;

  • In order for a[1].d to be 8-byte aligned, the overall struct size must be a multiple of 8, so there must therefore be 4 bytes of padding after a[0].s.

If you re-order the struct from largest to smallest:

typedef struct structc_tag
{
   double      d;
   int         s;
   char        c;
} structc_t;

...then the only padding required is 3 bytes after .c, to make the structure size a multiple of 8. This results in the total size of the struct being 16, rather than 24.

2
votes

It's platform dependent, but it depends on what double is aligned to. If it's aligned to 8 bytes, which appears to be this case, 3 bytes of padding won't cut it.

If double was aligned to 4 bytes, you'd be right and 3 bytes of padding would be used.