共用体編集

共用体型( union type )は、メンバー・オブジェクトのオーバーラップする空でないセットを記述します[1]。 それぞれのオブジェクトは、オプションで指定された名前と、場合によっては異なるタイプを持っています。

共用体の構文は、構造体と似ていますが[2]、共用体の全てのメンバーはメモリー上の一箇所に格納されている点が異なります。 共用体のサイズは、共用体のもっとも大きなメンバーのサイズになります。

演習
構造体のメンバーと共用体のメンバーのアドレスについて考えてみましょう。

共用体の定義編集

共用体を定義し、共用体タグを使って共用体変数を宣言します。

共用体タグの定義
union タグ名 {
	データー型 メンバー名;
		:
		:
};

共用体の宣言編集

共用体変数の宣言
union タグ名 変数名リスト;

共用体タグの定義と共用体の宣言とを同時に行うこともできる。

共用体タグの定義と共用体の宣言とを同時に行う
union タグ名 {
	データー型 メンバー名;
		:
		:
} 変数名リスト;

共用体のメンバーへのアクセス編集

形式
postfix-expression . identifier

構文は、構造体のメンバーへのアクセスと同一です[3]

共用体の例
#include <math.h>
#include <stdint.h>
#include <stdio.h>

int main(void) {
  for (double *p = (double[]){0.0, 1.0, -1.0, 2.0, NAN, INFINITY, -INFINITY, 999.0}; *p != 999.0; p++) {
    union {
      long l;
      double d;
    } u;
    u.d = *p;

    printf("%6.3f = %#18lx\n", u.d, u.l);
  }
}
実行結果
 0.000 =                  0
 1.000 = 0x3ff0000000000000
-1.000 = 0xbff0000000000000
 2.000 = 0x4000000000000000
   nan = 0x7ff8000000000000
   inf = 0x7ff0000000000000
  -inf = 0xfff0000000000000

long と double をメンバーとする共用体を用意してIEEE 75464ビット倍精度浮動小数点数のバイナリ表現を表示しました。 このコードは sizeof(long) == sizeof(double) == 8 であることを仮定しています。

倍精度浮動小数点数のビットレイアウト
 
共用体とビットフィールドの例
#include <math.h>
#include <stdint.h>
#include <stdio.h>

int main(void) {
  for (double *p = (double[]){0.0, 1.0, -1.0, 2.0, NAN, INFINITY, -INFINITY, 3.1415926536, 999.0}; *p != 999.0; p++) {
    union {
      long l;
      double d;
      struct {
          long fract : 52,
               exp : 11,
               sign : 1;
      };
    } u;
    u.d = *p;

    printf("%6.3f = %#18lx, sign = %s, exp = %d, fract = %d\n", u.d, u.l, u.sign ? "+" : "-", u.exp, u.fract);
  }
}
実行結果
 0.000 =                  0, sign = -, exp = 0, fract = 0
 1.000 = 0x3ff0000000000000, sign = -, exp = 1023, fract = 0
-1.000 = 0xbff0000000000000, sign = +, exp = 1023, fract = 0
 2.000 = 0x4000000000000000, sign = -, exp = -1024, fract = 0
   nan = 0x7ff8000000000000, sign = -, exp = -1, fract = 0
   inf = 0x7ff0000000000000, sign = -, exp = -1, fract = 0
  -inf = 0xfff0000000000000, sign = +, exp = -1, fract = 0 
3.142 = 0x400921fb544486e0, sign = -, exp = -1024, fract = 1413777120

脚註編集

  1. ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 31, §6.2.5 Types. オリジナルの2018-12-30時点によるアーカイブ。. https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf. "A union type describes an overlapping nonempty set of member objects, each of which has an optionally specified name and possibly distinct type." 
  2. ^ 共用体にはビットフィールドが無いのが大きな違いです。
  3. ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 59, §6.5.2.3 Structure and union members. オリジナルの2018-12-30時点によるアーカイブ。. https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf.