I have found a piece of code which declares union like this:
union vector_s {
struct {float x,y,z};
float m[3];
} v;
It may be like that, but it's not identical to it, since there are at
least two errors in that declaration. First, a semicolon is required
after ``z'' in the struct declaration. Second, this:
struct {float x,y,z;};
declares an anonyous type, but doesn't declare an object or member of
that type. Some compilers allow anonymous struct members as an
extension, so you could have the above declaration and refer to v.x,
but it's non-standard.
So in standard C you could have:
union vector_s {
struct {float x,y,z;} s;
float m[3];
} v;
and then, rather than v.z, you'd refer to v.s.z.
there is unnamed structure m ( matrix 1x3 ) which has same offset as
x, so they are aligned properly.
m is a one-dimensional array; I wouldn't call it a matrix.
The problem I have is, whether I can
safely write data to, lets say, v.m[2] and read same data from v.z?
Like:
v.m[2] = 1.25f;
assert (v.z == 1.25f);
I tried to find answer myself, but i was not successfull.
It's very likely to work, but it's not guaranteed. The compiler is
allowed to insert padding arbitrarily between struct members, or after
the last member. The only real restrictions are that there can be no
padding at the beginning of a structure, and the members have to be
allocated in their declared order. Array elements, on the other hand,
*must* be allocated consecutively; there can be no padding between
them.
Having said that, it's hard to imagine a compiler inserting padding
between the members of the struct, so what you're doing will almost
certainly work. It's just not *guaranteed* to work -- which means
that it's one more think you'll have to consider if you're tracking
down a bug in the program.
If you really want to be able to access x, y, and z either as array
elements or as struct members, you can play some ugly tricks with the
preprocesor:
union vector_s {
float m[3];
} v;
#define x m[0]
#define y m[1]
#define z m[2]
so ``v.z'' expands to ``v.m[2]''. But a cleaner way to do this is:
enum {x, y, z};
union vector_s {
float m[3];
} v;
which lets you refer to v.m[2] as v.m[z].
(Presumably the real code has better names than m, v, x, y, and z.)