union (共用体)について
この記事では、C言語におけるunionの内容と使用方法について記載する。
1. 目的
・unionの意味ついて知る。
・union使い方を知る。
目次
2. union(共用体)とは
・同じメモリ領域を複数のメンバが共有するデータ型の一つ
(各々の要素は、名前が付けられ、メンバと呼ぶ)
・同じメモリ領域を使用し、様々な種類のデータを入れる場合に使う。
・同じ場所にデータを格納する以外は、構造体に似ている。
・メモリが節約できるメリットがある。
参考:
・C言語 共用体 union【メモリをシェアする考え方と使い方】
・【C言語入門】union(共用体)の使い方 | 侍エンジニアブログ
3. unionの使い方
・使用方法:
(1) union(共用体)の作成
typedef union {
データ型 メンバ名1;
データ型 メンバ名2;
データ型 メンバ名3;
・・・ ・・・;
}共用体名;
例:
typedef union{
char c_unum;
int i_unum;
}UNIONA;
(2) union(共用体)の宣言
共用体名(型) 共用体変数;
共用体変数.メンバ名 = xx;
例:
UNIONA uni; ///< 共用体の宣言
※使い方としては基本的に構造体と一緒
ここではtypedefを使用しているがtypedefを使用しない方法もある。
下記構造体の記事を参照
→組み込みC言語基礎知識7(構造体1) - Project_OKI’s diary
3. プログラム作成(共用体のサイズ確認)
(1 )共用体と構造体を作成し、それぞれのサイズを確認する。
#include <stdio.h> ///共用体の作成 typedef union{ char c_unum; int i_unum; }UNIONA; ///構造体の作成 typedef struct{ char c_snum; int i_snum; }STRUCTA; int main(void){ /// 宣言 UNIONA uni; ///< 共用体の宣言 STRUCTA st; ///< 構造体の宣言 ///サイズ確認 printf("uni_size=%lu\n",sizeof(uni)); ///共用体のサイズ printf("uni.c_unum_size=%lu\n",sizeof(uni.c_unum)); ///共用体のサイズ printf("uni.i_unum_size=%lu\n",sizeof(uni.i_unum)); ///共用体のサイズ printf("st_size=%lu\n",sizeof(st)); /// 構造体のサイズ printf("st.c_snum_size=%lu\n",sizeof(st.c_snum)); /// 構造体のサイズ printf("st.i_snum_size=%lu\n",sizeof(st.i_snum)); /// 構造体のサイズ }
実行結果:https://paiza.io/projects/EbWIRmC40l9akrxXnRTNLQ
・uniは、サイズが4、stはサイズが8となる。
・共用体のuniは、int とcharが同じメモリ領域を使用する為、
intとcharのサイズの最小値となる。
・構造体は、intとcharの宣言した分増えていく。
(2 )共用体と構造体を作成し、それぞれのサイズを確認する。(数増加)
#include <stdio.h> ///共用体の作成 typedef union{ char c_unum; int i_unum; int i_unum2; int i_unum3; int i_unum4; }UNIONA; ///構造体の作成 typedef struct{ char c_snum; int i_snum; int i_snum2; int i_snum3; int i_snum4; }STRUCTA; int main(void){ /// 宣言 UNIONA uni; ///< 共用体の宣言 STRUCTA st; ///< 構造体の宣言 ///サイズ確認 printf("uni_size=%lu\n",sizeof(uni)); ///< 共用体のサイズ printf("st_size=%lu\n",sizeof(st)); ///< 構造体のサイズ }
実行結果:https://paiza.io/projects/Q5haSqZta64MdGwYKFRyKQ?language=c
・上記の場合でも共用体のサイズは4となる。
・それに対し構造体のサイズは20となる。
3. プログラム作成(共用体の使用:値の代入)
(1)共用体に値を代入
#include <stdio.h> ///共用体の作成 typedef union{ short c_unum; int i_unum; }UNIONA; int main(void){ /// 宣言 UNIONA uni; ///< 共用体の宣言 uni.c_unum = 1; printf("uni_size=%d\n",uni.c_unum); ///< 共用体のサイズ printf("uni_size=%d\n",uni.i_unum); ///< 共用体のサイズ uni.i_unum = 2; printf("uni_size=%d\n",uni.c_unum); ///< 共用体のサイズ printf("uni_size=%d\n",uni.i_unum); ///< 共用体のサイズ }
実行結果:https://paiza.io/projects/lysUnWQ2M82Fcy0Zpl_BCQ?language=c
・メモリを共有している為、uni.c_unumに1を入れると、uni.i_unumも同じ値となる。
・uni.i_unumに2を入れるとuni.c_unumも同じ値となる。
3. プログラム作成(共用体の使用:構造体のメモリ削減)
(1)共用体を使用した構造体使用時のメモリ削減
#include <stdio.h> ///構造体の作成 typedef struct{ int test1; int test2; }TEST; typedef struct{ int point1; int point2; int point3; }POINT; typedef struct{ int oder1; int oder2; }ODER; ///共用体の作成 typedef union{ TEST tes; POINT poi; ODER ode; }UNIONA; int main(void){ /// 宣言 UNIONA uni; ///< 共用体の宣言 /// 共用体のサイズ確認 printf("uni_size=%lu\n",sizeof(uni)); /// 構造体のサイズ確認 printf("uni.tes_size=%lu\n",sizeof(uni.tes)); printf("uni.poi_size=%lu\n",sizeof(uni.poi)); printf("uni.ode_size=%lu\n",sizeof(uni.ode)); uni.tes.test1 = 1; ///< 構造体tes.test1に1を代入 printf("test1=%d\n",uni.tes.test1); uni.poi.point1 = 2; ///< 構造体poi.point1に2を代入 printf("test1=%d\n",uni.tes.test1); printf("test1=%d\n",uni.poi.point1); }
実行結果:https://paiza.io/projects/83sL9xvUuXzmCd7hgSrriQ?language=c
(a) 通常、構造体TEST、POINT、ODERを使用したい場合、
それぞれ構造体を宣言する。
その場合、使用メモリは、28byteになる。
しかし、この構造体(TEST、POINT、ODER)を同時に使わないので、
メモリを省略したい場合がある。
その時、上記のようにunionを使用することで、
12byteで3つの構造体を使用することが可能となる。
構造体の関連記事:
・C言語基礎知識7(構造体1) - Project_OKI’s diary
・C言語基礎知識17(構造体とポインタとアロー演算子の使い方) - Project_OKI’s diary
・C言語基礎知識26(構造体の配列) - Project_OKI’s diary
・C言語基礎知識27(構造体を複数の別ファイルで使用する) - Project_OKI’s diary
・C言語基礎知識28(構造体の中で構造体を宣言する) - Project_OKI’s diary
※基本的な使い方は構造体と同じ為、他の使い方については構造体の記事を参照
関連記事
C言語:
・組み込みの為のC言語基礎知識1(printf) - Project_OKI’s diary
・C言語基礎知識2(for分で処理を繰り返す) - Project_OKI’s diary
・C言語基礎知識3(配列) - Project_OKI’s diary
・知らないと損するお金の話(ふるさと納税、確定申告とワンストップ納税どっちが得?) - Project_OKI’s diary
・STM32マイコン_2(UART通信:TeraTermにHellow表示) - Project_OKI’s diary
・STM32マイコン_3(UART通信:複数文字送信) - Project_OKI’s diary