トップページ⇒tech
42コメント15KB

共用体とは?

■ このスレッドは過去ログ倉庫に格納されています
0001C学習者NGNG
共用体(union)って本を読んでもいまいちよくわからないです。
要するに変数の型に幅を持たせて、
様々な型を一つの変数で対応してしまおうっていうことですか?
0002名無しさん@お腹いっぱい。NGNG
CD屋の事です。ゲームや本なんかも売ってます。今もあったかな?
0003名無しさん@お腹いっぱい。NGNG
つーか、
共用体は、列挙したメンバのうち、一番大きな変数のサイズになります。
0004C学習者NGNG
>>3
それは
union foobar{
int a;
float b;
char c[10];
} hoge;
だとすると

sizeof hogeは10ということですか?

それと概要は最初に書いたことで問題ないですか?
0005名無しさん@お腹いっぱい。NGNG
型が沢山存在する言語(コンパイラ/インタプリタ)なんかを作るときとかに便利なんで使われます。
C++ではデータを抽象化すれば良いのであまり使われません。

Cでも最大サイズさえわかってれば汎用ポインタ型(void *)で代用できます。
型チェックがコンパイラ側でされるので、共用体の方が安全ですが、列挙した型しか使えないという制限があります。
あと、あなたは質問スレッド逝ってください。
0006名無しさん@お腹いっぱい。NGNG
>>4
sizeof(a) == 4
sizeof(b) == 4
sizeof(c) == 10
だとすると、
その場合はcのサイズになります。

sizeof演算子で各メンバのサイズを調べてください。
その中の最大の変数のサイズです。
0007C学習者NGNG
失礼しました。
0008名無しさん@お腹いっぱい。NGNG
たまにこういうの使う。
union{
  unsigned char byte;
  struct{
   unsigned b0 : 1;
   unsigned b2 : 1;
   unsigned b3 : 1;
   unsigned b4 : 1;
   unsigned b5 : 1;
   unsigned b6 : 1;
   unsigned b7 : 1;
  }bit;
}B;
B.byte で1バイトのunsigned char 型変数を操作(1バイトなので0〜255)。
B.bit.b0 〜 B.bit.b7 で B.byte の内容はビット単位で操作できる(1ビットなので1か0)
byte と bit のメモリ空間は同じで、どちらかを変更すればもう一方も変更されている。
わっかるかな〜?
00098NGNG
ギャ。上位と下位ビット逆だし。
unsigned b7 : 1;
unsigned b6 : 1;
unsigned b5 : 1;
unsigned b4 : 1;
unsigned b3 : 1;
unsigned b2 : 1;
unsigned b1 : 1;
unsigned b0 : 1;
だった。

ついでに byteの値が 0xe5 の場合。
ビット(2進数)で表すと 11100101 なわけで、
それぞれ b7 〜 b0 の状態になるわけだな。
今考えるとビットにする必要もなかったけどな…
0010C学習者NGNG
なるほど、変わった使い方ですね。
それに構造体と共用体の違いを説明するのに使えそうですね。

違いというか別物ですかね(汗)
00118NGNG
うーん、ていうか状態フラグとか受け渡すのによく使ってたので別段変わってはいないと思う。
つってもハードウェアあまりいじらないんなら関係ないだろうけど。
もっと単純なやつなら

union{
  char c[2];
  short s;
}
とすれば s (2バイト)の上位バイトと下位バイトを c (1バイトx2)で操作できるよな。
0012名無しさん@お腹いっぱい。NGNG
8@`9は間違いだと思うけど?
ミスだと思うが、ビットフィールドの型がunsignedになってるよ。

アラインメントの問題とは一切関係ないからね。>1
極端な例として
union {
struct {
char a;
short b;
} a;
char b[3];
} u ;
のサイズは何も設定しないとコンパイラ毎に異なります。(3だったり4だったり)
0013C学習者NGNG
今サーバからのデータの取得で、

type struct{
short mode; // A〜C のどれであるかのフラグ
union {
A a;
B b;
C c;
} body;
} hoge;
(A@`B@`Cが構造体)

こういう型のデータをとってこなきゃならないのをやってまして。
大変参考になりました。
0014名無しさん@お腹いっぱい。NGNG
ビットフィールドや共用体のメンバの配置はほとんど処理系依存だから
使わないにこしたことはない。

goto並に慎重に。
0015名無しさん@お腹いっぱい。NGNG
ふつービットフィールドなんて使わないっしょ
00168NGNG
>>14
処理依存については同意ー。確かに普通使わないですわ。
>>12
ごもっとも。正しいです。サンキュ。
u のサイズ変動も気を付けないといかんですね。
同じ処理系しか使ってない証拠でした。うわっカコワルっ。
0017名無しさん@お腹いっぱい。NGNG
>>13
 Cで書く場合は unionとstructの組み合わせを使うより
 いっそchar配列で取ってしまって
 アクセス関数を書いた方がいいかもしれんよ。
 そういう処理系依存の部分を関数内に全部まとめてしまう
0018名無しさん@お腹いっぱい。NGNG
>>15
おれはビットフィールドよく使うよ。
RAMの制約があったり、通信なんかでヘッダによってビット分けが違う場合とかね。
0019名無しさん@お腹いっぱい。NGNG
>>12 unsignedだと何がまずいんでしょうか。
0020名無しさん@お腹いっぱい。NGNG
11は終わってる。
00218NGNG
>>18 ちょっと安心
>>19 unsigned = unsigned int だから。
>>20 うん。
0022名無しさん@お腹いっぱい。NGNG
BCC系のどれだったかのバージョンで
ビットフィールドの型によっては連続しない場合があったよ
ビットフィールド派の人 ご注意。
0023名無しさん@お腹いっぱい。NGNG
>>21
unsigned = unsigned int だから何がまずいの?
0024名無しさん@お腹いっぱい。NGNG
>>23 21じゃないけど、char とunsignedのunionだからでしょう
0025名無しさん@お腹いっぱい。NGNG
>>24
8@`9は「charとunsignedのunion」に見えないのだけれども
それは俺の気のせいなのだろうか。
1. ビットフィールド自体の幅はどのみち指定したビット数になる
2. K&R(第二版)では(signed/unsigned)intのみがビットフィールドの
  型指定として正しい、という記述があるが、俺の知る限りでは
  少なくともgccやVC++は整数型であれば何でも通すようだ。
3. その他の、paddingやalignmentに関する問題はどのみち全て処理系依存であろう。

という訳で、俺もなぜunsignedが間違いと言いきれるのか、
さっぱり分からない。
002625NGNG
↑すまん書いた直後に理解した。
という訳で、無視してくれてよし。
0027名無しさん@お腹いっぱい。NGNG
>>26 俺わからん、解説お願い
0028名無しさん@お腹いっぱい。NGNG
組みこみやってると>>8と同じくビットフィールドを多用するだけに気になる。
共用体定義部のunsigned charは
unsigned intと、charの二重定義でメンバになり得るてこと?
002924NGNG
だから共用体のサイズが unsinged int 幅になるからでしょう
char が8ビット intが16bitだったら困るでしょう?

もし char で ビットフィールド定義したとしても、希望通り
動くかどうかは保証されないしね。

俺はビットフィールドより論理演算の方が好きだな
003027NGNG
そうか、そういう使い方ありなのか...やっとわかった。
でも本来は syntax error エラーだよね。
0031名無しさん@お腹いっぱい。NGNG

C++または OO を知っている方なら、容易にわかることですが、
union はCでpolymorphismを実現する手段だと捕らえるのが
わかりやすいと思います。
0032名無しさん@お腹いっぱい。NGNG
そ、そんなすごいものだったとわ!
0033>31NGNG
ぜ、ぜひ具体例を......
0034名無しさん@お腹いっぱい。NGNG
>>29
そもそもアライメントもパディングもエンディアンも処理系依存なんだし、
それを見越した上でのコーディングなら問題ないんじゃないの?
ビットフィールドで unsigned 以外の型って規格外だった様な気がするん
だけど、今は普通に使えるんだったかな?この辺うろ覚え。
論理演算の方が良いという意見には同意。
0035名無しさん@お腹いっぱい。NGNG
 制御系でビットフィールド使う局面はあるだろうけど、
論理演算の方が好みだな。K&R2版ではただのintでもいいが
明示的にsigned / unsignedを書いた方が良いって感じで
載ってたな。
 エンディアンは処理系依存っつーか狭義にはマシン依存だね。
 ビットフィールドも論理演算もその辺の依存性に気を
使わなきゃならんのは同じではあるな。
0036名無しさん@お腹いっぱい。NGNG
誰も書かないので…
1ビットのフィールドがintだったら、2の補数系なら取りうる値は-1か0。
フラグとして使うなら、普通はunsignedにするのが吉。
もちろん、unsigned intをunsignedと書いても問題なし。
ちなみに、14の言う通り、ビットフィールドがどうマッピングされるかは
全くの処理系依存。エンディアンとは関係ないし、CPU依存でもない。
0037名無しさんNGNG
type record case of
0038奥さん、名無しですNGNG
共用体とは、共用の体ということですな。
つまりは風俗のお姉さん。
本で調べたら、吉原あたりに繰り出してください>1
0039名無しさん@お腹いっぱい。NGNG
int main(void) {
printf("size of hoge = %d\n"@` sizeof(hoge));
#include <stdio.h>

union foobar {
int a;
float b;
char c[10];
} hoge@` hogege[2];

int main(void) {
printf("size of hoge = %d\n"@` sizeof(hoge));
#include <stdio.h>

union foobar {
int a;
float b;
char c[10];
} hoge@` hogege[2];

int main(void) {
printf("size of hoge = %d\n"@` sizeof(hoge));
printf(" hogege[0] == %p @` &hogege[0] %% 4 ==%d\n"@`
&hogege[0]@` (long)&hogege[0] % 4);
printf("(hogege[0] + 10) %% 4 == %d\n"@` ((long)&hogege[0] + 10) % 4);
printf(" hogege[1] == %p\n"@` hogege + 1);
return 0;
}
0040名無しさん@お腹いっぱい。NGNG
% cc hoge.c
% ./a.out
size of hoge = 12
hogege[0] == 0x804962c @` &hogege[0] % 4 ==0
(hogege[0] + 10) % 4 == 2
hogege[1] == 0x8049638
0041名無しさん@お腹いっぱい。NGNG
共用体とは、要は「同じ場所の使い回し」である。
自治会の集会所のような大きさの決まったスペースを、
ある時は16人でギター教室(新堀ギター?)、ある時は32人でアニメ上映会、
またある時は仕切りを付けて手芸教室と管理組合の会合(それぞれ8人)
と縦横無尽に使うことなのだ。

union 集会所 {
  16人部屋   ギター教室;
  32人部屋   アニメ上映会;  // アニオタ逝ってよし!!
  struct {
     8人部屋 手芸教室;
     8人部屋 管理組合;
  }
};

sizeof(集会所)は、32よりは大きいはずだ。
ちょっと強引だが、まあこんなもんでいいだろ。

共用体のメンバに構造体があってわかりにくかったか?
配列にしたかったら、
   8人部屋  団地の各棟の集会[4];
とか適当に喩えてくれ。
004241NGNG
> sizeof(集会所)は、32よりは大きいはずだ

ゴメン。変なことを書いた。寝よう。
■ このスレッドは過去ログ倉庫に格納されています