構造体 "と "ユニオン "の違いを示す良い例はありますか?
基本的には、struct
はそのメンバーのすべてのメモリを使用し、union
は最大のメンバーのメモリスペースを使用するということを知っています。他にOSレベルでの違いはありますか?
ユニオンでは、すべての要素が同じ場所に格納されているため、いずれかの要素だけを使用することになります。そのため、複数の型になる可能性があるものを格納したい場合に便利です。一方、構造体は、要素ごとに独立したメモリの場所を持ち、すべての要素を一度に使用することができます。
具体的な使用例を挙げると、私は少し前にSchemeのインタープリタを作っていて、C言語のデータ型の上にSchemeのデータ型を重ねていました。これは、構造体に値の型を示すenumと、その値を格納するunionを格納するというものだ。
union foo {
int a; // can't use both a and b at once
char b;
} foo;
struct bar {
int a; // can use both a and b simultaneously
char b;
} bar;
union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!
struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK
編集: x.bを 'c'に設定するとx.aの値が何に変わるのか気になるところですが、技術的には未定義です。最近のマシンでは、charは1バイト、intは4バイトなので、x.bに 'c'という値を与えると、x.aの第1バイトにも同じ値が与えられます。
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
プリント
99, 99
なぜこの2つの値は同じなのでしょうか?int 3の最後の3バイトはすべて0なので、99とも読めるからです。x.aにもっと大きな数字を入れると、必ずしもそうではないことがわかります。
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
プリント
387427, 99
実際のメモリの値を詳しく見るために、16進数で設定してプリントアウトしてみましょう。
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
プリント
deadbe22, 22
0x22が0xEFを上書きしているのがよくわかります。
BUT。
このプログラムは、私のMacでは0xEFを0x22に上書きしましたが、他のプラットフォームではintを構成するバイトの順序が逆なので、代わりに0xDEに上書きされてしまうことがあります。したがって、プログラムを作成する際には、ユニオン内の特定のデータを上書きするという動作は、ポータブルではないので、決して当てにしてはいけません。
バイトの順序についての詳しい読み物は、endiannessをご覧ください。