To elaborate on the answer provided by Angew quoting the standard concerning anonymous unions and structs, I thought to provide an sample of C source code with the output generated by that sample showing how values are allocated within a struct
and a union
composed of struct
and union
components.
The standard quoted by Angew is:
For the purpose of name lookup, after the anonymous union definition,
the members of the anonymous union are considered to have been defined
in the scope in which the anonymous union is declared.
The source code of a struct
composed of named and anonymous structs and unions looks like the following. This is using Visual Studio 2005 and the #pragma (pack, 1)
is used to align everything on a char
boundary in order for there to be no memory holes. There is also a simple C Preprocessor macro defined to make the output more legible and easier to code.
typedef unsigned char UCHAR;
// use of Microsoft Visual Studio pragma to force char alignment for the struct.
#pragma pack(push, 1)
const struct {
union {
const UCHAR myArray[]; // this array shares memory with struct following
struct {
const UCHAR iOne;
const UCHAR iTwo;
const UCHAR iThree;
}; // anonymous struct accessed by specifying Things.
}; // anonymous union accessed by specifying Things.
// const UCHAR myArray[]; // will cause error - "error C2020: 'myArray' : 'struct' member redefinition"
union {
const UCHAR myArray[]; // this array shares memory with struct following
struct {
const UCHAR iOne;
const UCHAR iTwo;
const UCHAR iThree;
} s; // named struct accessed by specifying Things.u.s
} u; // named union accessed by specifying Things.u
} Things = {1, 2, 4, 8, 9, 10, 22, 23, 24, 25};
#pragma pack(pop)
// a little helper macro to make the output easier to code.
#define PRINTF_VAL(x) printf ("%s %d \n", #x, x)
int itSelf (UCHAR iMask)
{
int iMatch = -1;
int jj = 0;
jj = Things.myArray[0]; PRINTF_VAL(Things.myArray[0]);
jj = Things.myArray[1]; PRINTF_VAL(Things.myArray[1]);
jj = Things.myArray[2]; PRINTF_VAL(Things.myArray[2]);
jj = Things.myArray[3]; PRINTF_VAL(Things.myArray[3]);
jj = Things.myArray[4]; PRINTF_VAL(Things.myArray[4]);
jj = Things.iOne; PRINTF_VAL(Things.iOne);
jj = Things.iTwo; PRINTF_VAL(Things.iTwo);
jj = Things.iThree; PRINTF_VAL(Things.iThree);
jj = Things.u.myArray[0]; PRINTF_VAL(Things.u.myArray[0]);
jj = Things.u.myArray[1]; PRINTF_VAL(Things.u.myArray[1]);
jj = Things.u.myArray[2]; PRINTF_VAL(Things.u.myArray[2]);
jj = Things.u.myArray[3]; PRINTF_VAL(Things.u.myArray[3]);
jj = Things.u.myArray[4]; PRINTF_VAL(Things.u.myArray[4]);
jj = Things.u.s.iOne; PRINTF_VAL(Things.u.s.iOne);
jj = Things.u.s.iTwo; PRINTF_VAL(Things.u.s.iTwo);
jj = Things.u.s.iThree; PRINTF_VAL(Things.u.s.iThree);
return iMatch + 1;
}
The output generated by this function looks like:
Things.myArray[0] 1
Things.myArray[1] 2
Things.myArray[2] 4
Things.myArray[3] 8
Things.myArray[4] 9
Things.iOne 1
Things.iTwo 2
Things.iThree 4
Things.u.myArray[0] 8
Things.u.myArray[1] 9
Things.u.myArray[2] 10
Things.u.myArray[3] 22
Things.u.myArray[4] 23
Things.u.s.iOne 8
Things.u.s.iTwo 9
Things.u.s.iThree 10
The output shows the overlap between the various components of the main struct
, Things
caused by the use of unions. You can also see how the components of the anonymous struct
and union
are referenced versus those components of the named struct
and union
.
Also just for fun I tried adding an array definition of const UCHAR myArray[];
after the anonymous union
containing const UCHAR myArray[];
to see what would happen. The compiler complained with an error of error C2020: 'myArray' : 'struct' member redefinition
. The addition is commented out in the struct
definition of Things
above. However since the second use of const UCHAR myArray[];
is in a named union
the compile works because second use is accessed by specifying the name of the union.