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.
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
- Store -1.0 in
u.asFloatand work out which bit changed from 1.0. - Add a
KindBoolmember and abooleanfield toValue's union, and extendShowto print it.