1

I'm curious about the offsets of C++ struct members when the members are of mixed types. For instance:

#include <iostream>
#include <cstddef>
struct S {
    char c0;
    char carray[10];
    char c1;
    double d1;
};

int main()
{
    std::cout
        << "offset of char   c0 = " << offsetof(S, c0) << '\n'
        << "offset of double carray = " << offsetof(S, carray) << '\n'
        << "offset of double c1 = " << offsetof(S, c1) << '\n'
        << "offset of double d1 = " << offsetof(S, d1) << '\n';
}

The output is the following:

offset of char   c0 = 0                                                                                                                                       
offset of double carray = 1                                                                                                                                   
offset of double c1 = 11                                                                                                                                      
offset of double d1 = 16 

The offsets for c0, carray, and c1 are all easily understandable. I'm curious about d1. Why does it have an offset of 16 instead of the expected value of 12? It looks like it goes through some offset alignment.

Justin D
  • 11
  • 1
  • Alignment. Look up `alignof`. Doubles would be 8-byte aligned – ChrisMM Dec 22 '20 at 01:40
  • See also [Double alignment](https://stackoverflow.com/questions/11108328/double-alignment). – dxiv Dec 22 '20 at 01:41
  • alignment is why it's always recommended to put fields from large to small – phuclv Dec 22 '20 at 01:48
  • Why do you output `"offset of double carray = "` and `"offset of double c1 = "` when their declarations are `char carray[10]` and `char c1`? – JaMiT Dec 22 '20 at 02:00

1 Answers1

0

Compilers often align data to 4, 8 or 16 bytes for performance reasons or because of requirements imposed by the CPU. The C++ standard gives them great leeway in this regard.

double is often at a sizeof(double) aligned memory address for these reasons.

You can use the alignof operator to check the alignment of a particular object.

If the tightest possible packing, with no wasted space, is required for some reason, most compilers have custom keywords or attributes to request this instead of the usual alignment.

Tumbleweed53
  • 1,491
  • 7
  • 13
  • Note that tightest possible packing may break on the architectures for which the alignment is required, not merely beneficial for better performance. It's also typically dependent on non-portable syntax to request the packing. If you want a portable solution, just lay out the struct definition from most aligned to least aligned types, e.g. in this case, put `double d1;` first. – ShadowRanger Dec 22 '20 at 01:58