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
alignas
specifier). - 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
data
array 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
A
can bereinterpret_cast
to 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
data
array insidestruct A
.