web-dev-qa-db-ja.com

Cの「union」と「struct」の主な違いは何ですか?

重複の可能性:
Cの構造体と共用体の違い

構造体の意味が理解できました。しかし、私はunionとstructの違いに少し戸惑っています。連合は記憶の共有のようなものです。正確にはどういう意味ですか?

21
Vinay

ユニオンを使用すると、すべてのメンバーがsameメモリを共有します。構造体では、それらはメモリを共有しないため、構造体の各メンバーにメモリ内の異なるスペースが割り当てられます。

例えば:

union foo
{
 int x;
 int y;
};

foo f;
f.x = 10;
printf("%d\n", f.y);

ここでは、値10をfoo::xに割り当てます。次に、foo::yの値を出力します。これは、xとyが同じメモリを共有しているため、also10です。ユニオンのすべてのメンバーが同じメモリを共有するため、コンパイラは、ユニオンの最大メンバーに適合するのに十分なメモリを割り当てる必要があることに注意してください。したがって、charlongを含む共用体には、longを収めるために十分なスペースが必要になります。

しかし、構造体を使用する場合:

struct foo
{
 int x;
 int y;
};

foo f;
f.x = 10;
f.y = 20;
printf("%d %d\n", f.x, f.y);

Xに10を、yに20を割り当て、両方を出力します。 xとyは同じメモリを共有していないため、xは10、yは20であることがわかります。

編集:上記のGmanのコメントにも注意してください。私が組合に提供した例は、デモンストレーションのみを目的としています。実際には、ユニオンの1つのデータメンバーに書き込んでから、別のデータメンバーにアクセスするべきではありません。通常、これによりコンパイラはビットパターンを別のタイプとして解釈するだけですが、これを行うと 未定義の動作 であるため、予期しない結果が生じる可能性があります。

24
Charles Salvia

ユニオンを使用して、バイトを他のタイプとの間で変換しました。ビットシフトよりも簡単だと思います。

union intConverter {
    int intValue;
    struct {
        byte hi;
        byte lo;
    } byteValue;
}

intConverter cv;
cv.intValue =1100;
printf("%X %X\n", cv.byteValue.hi, cv.byteValue.lo);

ここで、intは16ビットです(マイクロコントローラーで使用されていました)。

10
Sam

ユニオンの各メンバーは同じメモリを共有します。つまり、1つを変更すると、他も変更されます。また、メンバーのタイプが異なる場合、予期しない結果が生じる可能性があります。 (正確には予測不可能ではありませんが、データメンバーを構成する基本的なビットパターンを認識していない限り、予測するのは困難です)。

4

これが何に役立つのかについて、思いがけない例がある方が便利な場合があります。 (ユニオンのほとんどのビットバンギングの使用は非常に危険であるため、「無意味」と言います。ビッグエンディアンからリトルエンディアンのハードウェアに移行したビットバンギングユニオンは、最も(最初は)神秘的な方法で壊れます。)(もちろん、私はライブラリーよりも桁違いに速い数学関数を実装するために浮動小数点数を分解するビットバンギング共用体を記述しました。どのメンバーが同じアドレスを持つことになっているかについてのアサーションを追加するだけです。)

 struct option1 {int type;/*他のメンバー* /}; 
 struct option2 {int type;/*他のメンバー* /}; 
 struct option3 {int type;/*他のメンバー* /}; 
 union combo {
 int type; //構造体のint型と正確にオーバーラップすることが保証されています。
 struct option1; 
 struct option2; 
 struct option3; 
}; 
// ... 
 void foo(union combo * in){
 switch(in.type){
 case 1:{struct option1 * bar = in; //次に、option1タイプのリクエストを処理します} 
ケース2:{struct option2 * bar = in; //次に、option2タイプのリクエストを処理します} 
ケース3:{struct option3 * bar = in; //次に、option3タイプのリクエストを処理します} 
} 

この種の構造は、Xプログラミングや、さまざまな種類のメッセージ(さまざまな引数とレイアウト要件)を受信できる関数を作成したいその他の状況で非常に一般的です。

3
Eric Towers

ユニオンについて考えることができる1つの方法は、ユニオンの各メンバーが特定のタイプの「エイリアス」である、メモリブロックに対するさまざまなタイプのエイリアスのセットであると考えています。各エイリアスは、メモリ内の同じアドレスを参照します。そのアドレスのビットがどのように解釈されるかは、エイリアスのタイプによって決まります。

ユニオンが占有するメモリの量は、常にユニオンの最大サイズの「メンバー」と同じか、場合によってはそれよりも大きくなります(配置の制限のため)。

2
Jeff Mercado

ここでのほとんどの答えは正しいです。ユニオンは基本的に、同じデータにさまざまな方法でアクセスする方法です(たとえば、4バイトのメモリに1つの整数または4文字としてアクセス/解釈できます)。ご存知のように、構造体は単純です。独自のメモリを持つさまざまな個別のオブジェクトのコレクションです。

通常、Structsと比較して、プログラミングのかなり後の段階でUnionが必要です。

1
JP19

このプログラムを実行して、出力を確認します。

#include <stdio.h>

 int main()[。 ]} testUnion; 
 
 struct _testStruct 
 {
 long long x; 
 long long y; 
} testStruct; 
 printf( "Sizeof Union%d\n"、sizeof(testUnion)); 
 printf( "Sizeof Struct%d\n"、sizeof(testStruct)); 
 return; 
} 
 

構造体のサイズはユニオンのサイズの2倍であることがわかります。これは、構造体が2つに割り当てているのに対し、unionは1つの変数にのみスペースを割り当てているためです。

1
Manoj R