3

According to this post, the alignment of struct is implementations specific, which implies different compiler will align the members in struct differently, giving different size of the same struct across compilers.

However, in this video, the speaker made it sound like the following structs must have the sizes of 16 and 12 across compilers:

#include <iostream> struct C { uint64_t x; uint32_t y; }; struct D { uint32_t x; uint32_t y; uint32_t z; }; int main() { std::cout << sizeof(C) << std::endl; std::cout << sizeof(D) << std::endl; } 

And they are indeed 16 and 12.

Why they have to be 16 and 12? Not 16 and 16?

11
  • "Why" what? It's not clear what you're asking about. That something can be different does not mean that it always will be different. Commented Jun 22, 2019 at 5:18
  • 1
    Either the speaker is wrong, or you misunderstood him. I think it's very likely that the structs will have the given sizes, but it's absolutely not guaranteed. Commented Jun 22, 2019 at 5:41
  • Well they will always be at least 16 and 12 on any system that requires alignment for 32 bit and 64 bit integers, that's for sure. Don't know any hardware that doesn't require that myself. Commented Jun 22, 2019 at 6:24
  • @NicolBolas sorry, didn't ask very clearly. updated. Commented Jun 22, 2019 at 6:50
  • 1
    catb.org/esr/structure-packing Commented Jun 22, 2019 at 7:42

1 Answer 1

5

And they are indeed 16 and 12.

They are of this size, given:

  • the compiler (& options) you used
  • your target platform
  • the absence of directives related to aligment/packing in the code

For your video, I guess the speaker just took a given platform/toolchain to develop his example. However in general, since sizeof(T) is compiler/platform dependent, std::atomic<T>::is_lock_free() is also compiler/platform dependent.

Examples

Using the following struct:

struct C { uint64_t x; uint32_t y; }; 

Different compilers & options

Target platform

Alignment/packing directives

Why these differences ?

Compilers are free to add unused bits/bytes after any field of a structure/class. They do so for performance reasons: on some platforms, it is faster to read/write a multi-byte int that verify certain alignment properties (usually, the address of a N-bytes int must be divisible by N).

Usually, it's convenient that your C++ compiler performs low level optimizations behind your back. Sometimes you want more control on this feature (non-exhaustive list of reasons):

  • when you serialize data which will be read by a different program (save to file, send to the network).
  • when memory usage is more important than execution speed.
  • in multicore & multithreaded program, controlling how many struct there are in a CPU cache line can limit cache invalidations between cores, which improves execution speed.

Which is why compilers usually provides utilities to control it.

TL;DR

The sizeof(T) doesn't "have" to be anything for a given T. It is compiler/platform dependent, and you can often override it with specific compiler directives.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.