【C言語】
union(共用体)を使ったスワップ関数の実装

バイトスワップ/エンディアン変換 union(共用体) の使い道 bswap_16, bswap_32, bswap_64

■unionと構造体との違いとは

簡単に言うと構造体のメンバを重ねて参照するのがunionです。

例えば
32bit(4byte)のメモリ領域を
1つの32bit変数として見たり
4つの8bit変数として見たりする時便利です。


16bitスワップ

#include  <stdio.h>
#include  <stdint.h>
//16bit(2byte)をスワップする
uint16_t  bswap_16(uint16_t x){
  union   {
    uint16_t  bit16;
    struct    {uint8_t  b1,b2;} bit8x2;  
  } y,z ;
  y.bit16 = x ;
  z.bit8x2.b1 = y.bit8x2.b2;
  z.bit8x2.b2 = y.bit8x2.b1;
  return  z.bit16 ;  
}
int main(void){
  for(uint64_t i = 0x0123456789abcdef  ; i != 0; i >>= 4){
    uint16_t u16 = i; 
    printf("%04X -> %04X\n",u16, bswap_16(u16));
  }
}

16bit(2byte)のメモリ領域を
1つの16bit変数として見たり
2つの8bit変数として見たりする例。

同じメモリ領域を bit16で参照したり、
bit8x2のb1、b2で参照したりできます。


32bitスワップ

#include  <stdio.h>
#include  <stdint.h>
//32bit(4byte)をスワップする
uint32_t  bswap_32(uint32_t x){
  union   {
    uint32_t  bit32;
    struct    {uint8_t  b1,b2,b3,b4;} bit8x4;  
  } y,z ;
  y.bit32 = x ;
  z.bit8x4.b1 = y.bit8x4.b4;
  z.bit8x4.b2 = y.bit8x4.b3;
  z.bit8x4.b3 = y.bit8x4.b2;
  z.bit8x4.b4 = y.bit8x4.b1;
  return  z.bit32 ;  
}
int main(void){
  for(uint64_t i = 0x0123456789abcdef  ; i != 0; i >>= 4){
    uint32_t u32 = i;
    printf("%08X -> %08X\n",u32, bswap_32(u32));
  }
}

32bit(4byte)のメモリ領域を
1つの32bit変数として見たり
4つの8bit変数として見たりする例。

bit32とbit8x4を重ねて参照します。


64bitスワップ

#include  <stdio.h>
#include  <stdint.h>
//64bit(8byte)をスワップする
uint64_t  bswap_64(uint64_t x){
  union   {
    uint64_t  bit64;
    struct    {uint8_t  b1,b2,b3,b4,b5,b6,b7,b8;} bit8x8;  
  } y,z ;
  y.bit64 = x ;
  z.bit8x8.b1 = y.bit8x8.b8;
  z.bit8x8.b2 = y.bit8x8.b7;
  z.bit8x8.b3 = y.bit8x8.b6;
  z.bit8x8.b4 = y.bit8x8.b5;
  z.bit8x8.b5 = y.bit8x8.b4;
  z.bit8x8.b6 = y.bit8x8.b3;
  z.bit8x8.b7 = y.bit8x8.b2;
  z.bit8x8.b8 = y.bit8x8.b1;
  return  z.bit64 ;  
}
int main(void){
  for(uint64_t i = 0x0123456789abcdef  ; i != 0; i >>= 4){
    uint64_t u64 = i; 
    printf("%016lX -> %016lX\n", u64, bswap_64(u64));
  }
}

64bit(8byte)のメモリ領域を
1つの64bit変数として見たり
8つの8bit変数として見たりする例。

bit64とbit8x8を重ねて参照します。


➡64bitスワップ実行例

./a.out
0123456789ABCDEF -> EFCDAB8967452301
00123456789ABCDE -> DEBC9A7856341200
000123456789ABCD -> CDAB896745230100
0000123456789ABC -> BC9A785634120000
00000123456789AB -> AB89674523010000
000000123456789A -> 9A78563412000000
0000000123456789 -> 8967452301000000
0000000012345678 -> 7856341200000000
0000000001234567 -> 6745230100000000
0000000000123456 -> 5634120000000000
0000000000012345 -> 4523010000000000
0000000000001234 -> 3412000000000000
0000000000000123 -> 2301000000000000
0000000000000012 -> 1200000000000000
0000000000000001 -> 0100000000000000