パソコン活用研究シリコンバレー(C、C++、の活用研究)

共用体

1. はじめに

共用体(Union)は、これもまたBASICにはない機能(データ型)で、初めて耳にする人には
わかりにくいもののひとつかもしれません。BASICに比べてCのとっきにくいにくい部分の
ひとつと言えるでしょう。

2. 共用体とは

1) 共用体の宣言
共用体は、(構造体と同じように)複数のデータ型をひとつにまとめて扱えるように考えられた
データ型で、その書式は構造体と同じです。
まず、共用体の宣言の書式からみてみましょう。


/*あとで共用体のメンバーとして使う構造体 c_byte の宣言*/
struct c_byte {
char low;
char high; };


/* 共用体宣言 */
union ux {         /*共用体タグ  「ux」という名称の新しいデータ型(共用体)の名前 */
short x;          /*共用体のメンバー*/
struct c_byte xbyte;   /*共用体のメンバー  構造体をメンバーとすることもできる*/
} u_x;            /*共用体変数名*/

書式は構造体と同じです。構造体をメンバーとすることもできます。


2) 共用体の領域の確保、メンバーの領域の割り付け
さて、上のように宣言すると、以下のことが行われます。
(1) メンバーの中でもっとも大きなデータサイズと同じ大きさの領域が、共用体の領域として確保
    されます。
(2) 各メンバーの領域は、すべて共用体変数の先頭アドレスから、割り付けれれます。
   言ってることがわかりにくいと思いますが、各メンバーは、共用体の領域を先頭アドレスから
   共用する(だぶって使用する)ということです。

と言っても、初めて聞く人には何のことかわからないと思います。ダブって領域を使用すると言われると
何に使うの?という人もいるでしょうし、あるいは、それって危険な使いかたじゃない?なんて感じる人も
いるかもしれませんね。BASICプログラマには理解しずらいところです。

では、もう少し上の例で具体的にみてみましょう。
上の例では、共用体uxのメンバーは、short型(2byte) と構造体struct c_byte(これも2Byteです)の
2つです。どちらもサイズは2Byteなので、この場合は、共用体uxの領域として2Byteが確保されます。

そして、それじれのメンバーの領域は共用体変数の先頭アドレスから割り付けられる、とは以下のように
領域が割り付けられるということです。

メモリー番地 M M+1
共用体 union ux  
short x  
struct c_byte xbyte char low char high

共用体の領域として、2Byte(番地としては、MとM+1)が確保されました。
short型のx は先頭から2Byte(番地 MとM+1)を割り当てられます。
構造体struct c_byteのxbyteは、どの領域を割り当てられるのでしょうか。
struct c_byteはchar型(1Byte)2つから構成されています。1つめの char lowが番地Mに割りつけられ
2つめのchar highは番地M+1に割り付けれれます。

このように、同一の番地を複数のメンバーで共用するためのデータ型が共用体です。


3) メンバーの参照
メンバーの参照は、構造体と同じで「.」を使います。共用体変数がポインタ変数のときは「->」になります。


4) 使用例
とりあえず、共用体とは何か、少しわかったところで、それって何につかうの?という疑問が残るかと
思います。
サンプルをあげながら活用方法について若干触れてみます。
以下のサンプルは、2Byteの16進数(0000〜FFFF)を入力し、上位1Byte、下位1Byteに分けて
表示するプログラムです。このように共用体を使うと、入力されたデータを1Byteづつに切り出す
というような作業が簡単に行えます。

union.c
/*共用体のテストプログラム*/

#include <stdio.h>

struct c_byte {
  char low;
  char high;  };

/* 共用体宣言 */
union {
  short x;
  struct c_byte  xbyte;
  }  u_x;

main()
{
printf("16進数を入力(4ケタ) :");
scanf("%04x",&u_x.x);
printf("\n 入力された数(16進数) %04x",u_x.x);
printf("\n 上位バイト %02x  :  下位バイト %02x  ",u_x.xbyte.high,u_x.xbyte.low);
} 

実行例


A:\>union
16進数を入力(4ケタ) :3f7c

入力された数(16進数) 3f7c
上位バイト 3f : 下位バイト 7c
A:\>union
16進数を入力(4ケタ) :ff45

入力された数(16進数) ff45                  
上位バイト ff : 下位バイト 45
A:\>


この例では共用体をあえて使う意義、便利さをそれほど感じないかもしれませんが、
とりあえず共用体とはこんなものというのは、おわかりいただけたとおもいます。

こんな活用の仕方をしたプログラムがUnsigned型と浮動小数点型の内部構造にありますので、ご参照
下さい。

3. 余談 Basicでやってみたら
上のunion.cでやっている上位ケタと下位ケタの分割くらいならあまり共用体のご利益はないかも
知れませんね。
Basicでもこの程度ならお茶の子さいさいです。試しにBasicで4ケタの整数を上位2ケタ、下位2ケタ
に分割するプログラムを作成してみます。(N88Basicですが、他のBasicでも同じでしょう)

10 input "4ケタの数値(10進数)入力",i
20 print "入力された数",i
30 print "上位 ";i\100;" 下位 ";i mod 100

なんか、この程度ならBasicの方が簡単ですね。
実行例は以下の通り

TopPage