Consider a reasonably smart compiler:
XMFLOAT3 foo = {1.0f, 2.0f, 3.0f};
auto bar = &foo.x;
bar[2] += 5.0f;
foo.z += 5.0f; // Since no previous expression referenced .z, I know .z==8.0
cout << foo.z; // So optimize this to a hardcoded cout << 8.0f
Replacing variable accesses and operations by known results is a common optimization. Here the optimizer sees three uses of .z
: the initial assignment, the increment and the final use. It can trivially determine the values at these three points, and substitute those.
Because struct members cannot overlap (unlike unions), bar
which is derived from .x
cannot overlap .z
so .bar[2]
cannot affect .z
.
As you see, a perfectly normal optimizer can produce the "wrong" result.