Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Unions

A union is declared like a record, but all its fields start at the same address. They are different ways of reading one block of memory, and the union is as large as its largest field.

'' A union's fields all start at the same address: they are different
'' views of one block of memory, as large as the largest field.
union Bits32
    as float32 asFloat
    as uint32 asInt
    as uint8 bytes( 0 to 3 )
end union

dim as Bits32 u
u.asFloat = 1.0
print "sizeof( Bits32 ) ="; sizeof( Bits32 )
print "1.0 as a float32 is the bit pattern &h"; hex( u.asInt, 8 )
print "its bytes, lowest address first:";
for i as int32 = 0 to 3
    print " "; hex( u.bytes( i ), 2 );
next
print

'' A union inside a type gives one slot two meanings. A field beside
'' it must record which meaning is current: the union cannot.
enum ValueKind
    KindInt
    KindFloat
end enum

type Value
    as ValueKind kind
    union
        as int64 i
        as float64 f
    end union
end type

sub Show( byref v as Value )
    if v.kind = KindInt then
        print "an int64:"; v.i
    else
        print "a float64:"; v.f
    end if
end sub

dim as Value a, b
a.kind = KindInt : a.i = 42
b.kind = KindFloat : b.f = 2.5
Show( a )
Show( b )
print "sizeof( Value ) ="; sizeof( Value ); ", i and f both at offset"; _
      offsetof( Value, i ); offsetof( Value, f )

Output

sizeof( Bits32 ) = 4
1.0 as a float32 is the bit pattern &h3F800000
its bytes, lowest address first: 00 00 80 3F
an int64: 42
a float64: 2.5
sizeof( Value ) = 16, i and f both at offset 8 8

Bits32 is four bytes, whichever field you use. Writing asFloat and reading asInt shows the bit pattern of the float32 value 1.0, and the bytes array shows the same four bytes one at a time. The lowest address holds the lowest byte, because every target is little-endian.

A union ... end union without a name, inside a type, gives one slot of the record two meanings: Value stores either an int64 or a float64 in the same eight bytes, which is why offsetof reports both i and f at offset 8. The kind field beside it says which one is current, and Show reads it before touching the union.

Pitfall

A union does not know which field was written last. Reading v.f after writing v.i compiles and runs, and gives you the integer's bits read as a float. Keep a field beside the union that records which member is live, and check it every time.

Activities

  1. Store -1.0 in u.asFloat and work out which bit changed from 1.0.
  2. Add a KindBool member and a boolean field to Value's union, and extend Show to print it.