Edit. I didn't see @salem c's post until after I posted this.
| I know that sizeof(MyStruct) will give me 16 bytes. |
Yes, it would probably be 16 bytes. It's not guaranteed, however - we could conceive of a (probably stupid) implementation that would yield a larger struct.
| When it comes to memory alignment however, does it actually take 16 bytes? |
Yes. Alignment is a property inherent to the
address of an object; the alignment of an object never affects that object's size.
The important distinction is that the alignment requirements of a
subobject can affect the alignment requirement and size of an object.
1 2 3 4 5 6
|
struct A { alignas(8) std::uint8_t x[1]; } a;
static_assert(sizeof(a) == 8);
static_assert(alignof(a) == 8);
static_assert(sizeof(a.x) == 1);
static_assert(alignof(a.x) == 8);
|
If we use the memory optimization tool
pahole to examine the layout of A, we'll get the following. C++ comments are mine:
struct A {
// x[1] spans starts at offset 0, and ends at byte 1
uint8_t x[1]; /* 0 1 */
// The size of the structure is 8 bytes; it requires one cache-line
// The structure has one member.
/* size: 8, cachelines: 1, members: 1 */
// 7 total bytes of padding in the structure;
/* padding: 7 */
// The object requires only 8 bytes of its last cache-line
/* last cacheline: 8 bytes */
}; |
Pahole:
https://linux.die.net/man/1/pahole
Note that the type A is effectively the same as
std::aligned_storage_t<1, 8>.
| I also assume it builds in the bitwise operations necessary to convert the alignment. |
I don't know what you mean. As I wrote above, alignment is inherent to the address of an object. Bitmath is not generally necessary (or even natural) to access an object that is naturally aligned.
| Is it compiler dependent? |
Yes.
| Do I need to provide my own bitwise logic in order to guarantee that the above structure only takes 16 bytes? |
If it's just a plain struct, make this static assertion:
|
static_assert(sizeof(MyStruct) == 16);
|
If you need to pack or unpack structures that are not naturally aligned, you can use vendor-specific language extensions, e.g., the GCC attribute
[[gnu::packed]] to allow the compiler to misalign the members of a class, or use
std::memcpy as I discussed before. Misaligned accesses are undefined behavior; be careful.
I suggest that you play around with
pahole on Matt Godbolt's page:
https://godbolt.org/z/UqlG-G