このブログ記事では、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.