■union(共用体)と構造体との違いとは
簡単に言うと構造体のメンバを重ねて参照するのがunionです。
例えば
32bit(4byte)のメモリ領域を
1つの32bit変数として見たり
4つの8bit変数として見たりする時便利です。
■union(共用体)を使った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で参照したりできます。
■union(共用体)を使った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を重ねて参照します。
■union(共用体)を使った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