無名共用体と構造体に関する標準を引用して Angew によって提供された回答を詳しく説明するために、C ソース コードのサンプルを提供し、そのサンプルによって生成された出力を提供して、およびコンポーネントstruct
でunion
構成される内で値がどのように割り当てられるかを示すことを考えました。struct
union
Angew が引用している標準は次のとおりです。
名前検索の目的で、匿名共用体の定義の後、匿名共用体のメンバーは、匿名共用体が宣言されているスコープで定義されていると見なされます。
struct
名前付きおよび無名の構造体と共用体で構成されるのソース コードは、次のようになります。これは Visual Studio 2005 を使用しており、メモリ ホールがないように#pragma (pack, 1)
すべてを境界に揃えるために使用されます。char
出力をより読みやすく、コーディングしやすくするために定義された単純な C プリプロセッサ マクロもあります。
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;
}
この関数によって生成される出力は次のようになります。
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
出力は、共用体の使用によって引き起こされたmain のさまざまなコンポーネント間のオーバーラップを示していますstruct
。また、匿名とThings
のコンポーネントがどのように参照され、名前付きとのコンポーネントがどのように参照されるかを確認することもできます。struct
union
struct
union
const UCHAR myArray[];
また、楽しみのために、匿名のunion
包含の後に配列定義を追加して、const UCHAR myArray[];
何が起こるかを確認してみました。コンパイラはerror C2020: 'myArray' : 'struct' member redefinition
. struct
上記の定義では、追加はコメントアウトされていますThings
。ただし、 の 2 番目の使用はconst UCHAR myArray[];
名前付きでunion
あるため、2 番目の使用は共用体の名前を指定することによってアクセスされるため、コンパイルは機能します。