1. ホーム
  2. c

[解決済み] ストラクチャーとユニオンの違い

2022-03-22 18:43:44

質問

の違いを説明する良い例はありますか? structunion ? 基本的に私は struct はそのメンバーのすべてのメモリを使用し union は、最大のメンバーのメモリ空間を使用します。他にOSレベルでの違いはあるのでしょうか?

解決方法は?

ユニオンの場合、すべての要素が同じ場所に格納されるため、どちらか一方だけを使用することになります。そのため、複数の型のいずれかになり得るものを格納したい場合に有効です。一方、構造体は、各要素が別々のメモリに格納され、すべてを一度に使用することができます。

具体的な使用例を挙げると、少し前にSchemeのインタプリタを作っていて、Schemeのデータ型をCのデータ型に重ねるということをやっていたんです。これは、構造体の中に値の型を示すenumとその値を格納するユニオンを格納するものだった。

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の最初のバイトも同じ値になります。

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を上書きしているのがよくわかると思います。

しかし

C言語では、intのバイトの並び順は は定義されていません。 このプログラムは私のMacでは0xEFを0x22で上書きしていますが、他のプラットフォームではintを構成するバイトの順番が逆になっているので、代わりに0xDEを上書きしてしまうものがあります。したがって、プログラムを書くときには、ユニオンの中の特定のデータを上書きする動作は移植性がないので、決して当てにしない方がよいでしょう。

バイトの並び順についてもっと詳しく知りたい方は エンディアン .