Consider the following simple struct:
struct A
{
float data[16];
};
My question is:
Assuming a platform where float is a 32-bit IEEE754 floating point number (if that matters at all), does the C++ standard guarantee the expected memory layout for struct A? If not, what does it guarantee and/or what are the ways to enforce the guarantees?
By the expected memory layout I mean that the struct takes up 16*4=64 bytes in memory, each consecutive 4 bytes occupied by a single float from the data array. In other words, expected memory layout means the following test passes:
static_assert(sizeof(A) == 16 * sizeof(float));
static_assert(offsetof(A, data[0]) == 0 * sizeof(float));
static_assert(offsetof(A, data[1]) == 1 * sizeof(float));
...
static_assert(offsetof(A, data[15]) == 15 * sizeof(float));
(offsetof is legal here since A is standard layout, see below)
In case this bothers you, the test actually passes on wandbox with gcc 9 HEAD. I have never met a combination of a platform and compiler which would provide evidence that this test may fail, and I would love to learn about them in case they do exist.
Why would one even care:
- SSE-like optimizations require certain memory layout (and alignment, which I ignore in this question, since it can be dealt with using the standard
alignasspecifier). - Serialization of such a struct would simply boil down to a nice and portable
write_bytes(&x, sizeof(A)). - Some APIs (e.g. OpenGL, specifically, say, glUniformMatrix4fv) expect this exact memory layout. Of course, one could just pass the pointer to
dataarray to pass a single object of this type, but for a sequence of these (say, for uploading matrix-type vertex attributes) a specific memory layout is still needed.
What is actually guaranteed:
These are the things that, to my knowledge, can be expected from struct A:
- It is standard layout
- As a consequence of being standard-layout, a pointer to
Acan bereinterpret_castto a pointer to its first data member (which is, presumably,data[0]?), i.e. there is no padding before the first member.
The two remaining guarantees that are not (as to my knowledge) provided by the standard are:
- There is no padding in between elements of an array of primitive type (I am sure that this is false, but I failed to find a confirmative reference),
- There is no padding after the
dataarray insidestruct A.