名前空間
変種
操作

共用体宣言

提供: cppreference.com
< c‎ | language

共用体は、記憶域がオーバーラップする、一連のメンバから構成される型です (記憶域が順番通りに連続的に確保される一連のメンバから構成される構造体型とは対照的です)。 一度に多くともひとつのメンバの値だけが共用体に格納できます。

共用体のための型指定子は、使用されるキーワード以外は、構造体の型指定子と同じです。

目次

[編集] 構文

union name(オプション) { struct-declaration-list } (1)
union name (2)
name - 定義中の共用体の名前。
struct-declaration-list - 任意個の変数宣言、ビットフィールド宣言、および static assert 宣言。 不完全型のメンバおよび関数型のメンバは使用できません。

[編集] 説明

共用体は、最も大きなメンバを保持するために必要なだけの大きさを持ちます (無名の末尾のパディングが追加されることはあります)。 それ以外のメンバは、その最も大きなメンバの一部と同じバイト内に確保されます。

共用体へのポインタは、そのいずれのメンバへのポインタにもキャストできます (共用体がビットフィールドを持つ場合は、共用体へのポインタはそのビットフィールドのベースとなる型へのポインタにキャストできます)。 同様に、共用体のいずれのメンバへのポインタも、囲っている共用体へのポインタにキャストできます。

共用体の内容をアクセスするために使用されるメンバが、値を格納するために最後に使用されたメンバと同じでない場合は、格納された値のオブジェクト表現が新しい型のオブジェクト表現として再解釈されます (型のパンニングと言います)。 新しい型のサイズが最後に書き込まれた型のサイズより大きい場合は、その足りない分のバイトの内容は未規定です (トラップ表現の可能性もあります)。

構造体と同様に、 name を持たない共用体型のメンバは無名共用体と言います。 無名共用体のすべてのメンバは、囲っている構造体または共用体のメンバとみなされます。 囲っている構造体または共用体も無名であれば、これは再帰的に適用されます。

struct v {
   union { // 無名共用体
      struct { int i, j; }; // 無名構造体
      struct { long k, l; } w;
   };
   int m;
} v1;
 
v1.i = 2;   // 有効。
v1.k = 3;   // 無効。 内側の構造体が無名ではありません。
v1.w.k = 5; // 有効。

構造体と同様に、共用体が名前付きのメンバ (ネストした無名構造体または無名共用体から取得したものを含みます) を一切持たずに定義された場合、プログラムの動作は未定義です。

(C11以上)

[編集] キーワード

union

[編集] ノート

構造体および共用体の初期化に関するルールについては構造体の初期化を参照してください。

[編集]

#include <stdio.h>
#include <stdint.h>
#include <assert.h>
 
int main(void)
{
    union S {
        uint32_t u32;
        uint16_t u16[2];
        uint8_t  u8;
    } s = {0x12345678}; // s.u32 がアクティブメンバになります。
    printf("Union S has size %zu and holds %x\n", sizeof s, s.u32);
    s.u16[0] = 0x0011;  // s.u16 がアクティブメンバになります。
    // s.u32 または s.u8 からの読み込みはオブジェクト表現を再解釈します。
//  printf("s.u8 is now %x\n", s.u8); // 未規定。 一般的には 11 または 00 です。
//  printf("s.u32 is now %x\n", s.u32); // 未規定。 一般的には 12340011 または 00115678 です。
 
    // 共用体のどのメンバへのポインタもその共用体と等しくなります。
    assert((uint8_t*)&s == &s.u8);
 
    // この共用体は末尾に3バイトのパディングを持ちます。
    union pad {
       char  c[5];   // 5バイトを占めます。
       float f;      // 4バイトを占めます。 4バイトのアライメントを課します。
    } p = {.f = 1.23}; // float のアライメントを満たすため、共用体のサイズは8になります。
    printf("size of union of char[5] and float is %zu\n", sizeof p);
}

出力:

Union S has size 4 and holds 12345678
size of union of char[5] and float is 8

[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 6.7.2.1 Structure and union specifiers (p: 112-117)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.7.2.1 Structure and union specifiers (p: 101-104)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.5.2.1 Structure and union specifiers

[編集] 関連項目

共用体宣言C++リファレンス