このブログ記事では、C言語における共用体と構造体の違いについて紹介します。
共用体
共用体( 又はユニオン 英: union)は、C言語で異なる型の値を格納できる便利なデータ構造です。次の例をご覧ください。
union Data {
int x;
float y;
char z[16];
};unionの定義方法がstructと同じように見えますが、どう違うのでしょうか? structはすべての変数に対してメモリを確保しますが、
unionは最大の変数を格納するためのメモリしか確保しません。
struct Data1 {
int x;
float y;
char z[16];
};
int main () {
printf("unionのサイズ: %lu \n", sizeof(Data)); // => unionのサイズ: 16
printf("structのサイズ: %lu \n", sizeof(Data1)); // => structのサイズ: 24
Data data;
data.x = 1;
data.y = 3.14;
strcpy(data.z, "my data");
printf("x: %d, y: %f, z: %s", data.x, data.y, data.z);
// => x: 1978725, y: 0, z: my data
return 0;
}unionはchar配列のサイズ(16バイト)しかメモリを確保しませんが、structは24バイトを確保して、すべての変数が正しく格納されるようにします。
そのため、unionに値を代入すると、メモリに格納された値が書き換えられます。メモリを節約できるため、unionは1つの型だけが必要な場合や、
できるだけメモリを節約したい場合に便利です。
共用体 & 構造体
場合によっては、unionとstructを効果的に組み合わせることができます。
union Color {
struct { float r, g, b; } rgb;
struct { float c, m, y, k; } cmyk;
struct { float h, s, l; } hsl;
};
enum BufferType { Char, Float, Double };
struct Buffer {
BufferType type;
union {
char x[1024];
float y[1024];
double z[1024];
} data;
};ColorとBufferの例は、unionとstructを適切に組み合わせて使用する方法を示しています。
構造体のパディング
構造体を定義してそのサイズを出力すると、予想以上のメモリが割り当てられていることに気づくかもしれません。
struct Data {
char x; // 1バイト
int y; // 4バイト
};
int main () {
Data data;
printf("structのサイズ: %luバイト\n", sizeof(data));
// => structのサイズ: 8バイト
return 0;
}intとcharを合わせると5バイトしか必要ないはずですが、structのサイズは8バイトです。これは、CPUがメモリにアクセスする方法に関連しています。
CPUは1バイトずつではなく、通常4バイトの塊でメモリにアクセスします(デバイスにより異なります)。xとyが5バイトしか割り当てられていない場合、
yを取得するには2回アクセスする必要があります。一方で、xとyの間にパディングを追加して、それぞれが4バイトを占めるようにすると、CPUは1回の
アクセスでそれぞれを取得できます。これが、可能であればunionを使用してメモリを節約したい理由の一つです。
パディングの理解は、structの構築を最適化する際にも役立ちます。
struct Data1 {
char x;
int y;
char z;
};
struct Data2 {
int y;
char x;
char z;
};
int main () {
printf("Data1のサイズ: %lu \n", sizeof(Data1));
printf("Data2のサイズ: %lu \n", sizeof(Data2));
// => Data1のサイズ: 12
// => Data2のサイズ: 8
return 0;
}Data1とData2の違いは、変数が格納される順序だけですが、それが割り当てられるメモリの量に影響を与えます。Data1では、yが中央に配置されるため、
xとyの間にパディングが必要ですが、Data2では、yを最初に配置することで、xのパディングを不要にしています。
クイズ
この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。
リソース
- Portfolio Courses. 2023. Structure Padding | C Programming Tutorial. YouTube.
- Portfolio Courses. 2022. Union Data Types | C Programming Tutorial. YouTube.