共用体とは?
共用体はC言語で使うことができる特別なデータ型です。共用体は異なるデータ型が同じメモリ領域を共有できるところが特徴です。
共用体は構造体と同じように複数のメンバで定義することができるのですが、共用体はそれぞれのメンバが同じメモリ領域を共有しているので、メモリを効率的に使うことができます。
共用体の使い方
共用体を定義するためには、構造体を定義した時と全く同じ方法で定義しましょう。具体的には、以下のフォーマットにしたがって共用体を定義することになります。
1 2 3 4 5 6 7 8 9 10 11 |
#include <stdio.h> int main(void) { union u_data { int i; float j; char s[10]; }; } |
タグ(この場合はu_data)は任意に設定することができます。
また、int iやfloat jなどの各メンバは通常の変数と同じように定義することができます。
共用体の定義の最後で、セミコロン(;)の直前には、以下の例のように1つ以上の変数を任意で宣言することができます。
1 2 3 4 5 6 7 8 9 10 11 |
#include <stdio.h> int main(void) { union u_data { int i; float j; char s[10]; } data1, data2; } |
この定義の共用体は、int型やfloat型、そしてchar[]型を格納することができます。
共用体はint型やchar型などのはじめから用意されているプリミティブ型や、構造体などのユーザー定義型など、どんな型の変数でもメンバにすることができます。
共用体のメモリ占有量は、その共用体が保持しているメンバの中で、最もメモリ占有量が大きなメンバと同じになります。
実際に以下のコードで共用体が占めるメモリ領域を調べてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <stdio.h> union u_data { int i; float j; char s[100]; } data1, data2; int main(void) { union u_data data; printf("Memory size: %lu\n", sizeof(data1)); printf("Memory size i: %lu\n", sizeof(data.i)); printf("Memory size j: %lu\n", sizeof(data.j)); printf("Memory size s: %lu\n", sizeof(data.s)); return 0; } |
実行結果は
1 2 3 4 5 6 |
Memory size: 100 Memory size i: 4 Memory size j: 4 Memory size s: 100 |
となります。
これは、共用体のメモリ領域が各メンバの中でメモリ領域が最も大きいchar[100]と同じサイズだということです。
共用体のメンバにアクセスするには、ドット(.)演算子を使います。
共用体の名前とアクセスしたいメンバの間にドット(.)を書くことでアクセスすることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <stdio.h> #include <string.h> union u_data { int i; float j; char s[100]; } data1, data2; int main(void) { union u_data data; data.i = 150; data.j = 2.5; strcpy( data.s, "Test test test." ); printf("data.i: %d\n", data.i); printf("data.j: %f\n", data.j); printf("data.s: %s\n", data.s); return 0; } |
このコードでは共用体の各メンバにアクセスしています。
1 2 3 4 5 |
data.i: 1953719636 data.j: 77135212106908150064092232548352.000000 data.s: Test test test. |
という結果になります。
data.sは正しく表示できていますが、data.iやdata.jは値がちゃんと表示されていませんね。
これは、dataが共用体だからです。
各メンバが同じメモリ領域を共有しているので、最後に値が格納されたdata.sがメモリ領域を使用しているため、iやjは上書きされます。
逐次的に値を表示しているのが、以下のコード例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <stdio.h> #include <string.h> union u_data { int i; float j; char s[100]; } data1, data2; int main(void) { union u_data data; data.i = 150; printf("data.i: %d\n", data.i); data.j = 2.5; printf("data.j: %f\n", data.j); strcpy( data.s, "Test test test." ); printf("data.s: %s\n", data.s); return 0; } |
を実行すると、
1 2 3 4 5 |
data.i: 150 data.j: 2.500000 data.s: Test test test. |
と正しく表示できていることが分かります。