UNION
Declares a union user defined type.
Syntax:
Parameters:
typename
Name of the Union
fieldname
Name of a data field member
member function declaration
Any of the supported member functions
Description:
The data elements of a Union occupy a common space in memory (same memory address for all data elements of the Union). A data element of a Union can be a simple data field or an unnamed Type block of data fields.
The size of the Union is the size of the largest data element.
Since they occupy a common memory space, only one data element can usually be used at a given time (when a given data element is written, the other data elements sharing the common union space may be overwritten or mutilated).
Like Type, Union can use the optional Field = number specifier for field alignment, and supports also inheritance through the use of the Extends keyword.
Unlike Type, Union can not contain variable-length strings and arrays, and more generally can not have object fields (or bases) with constructors or destructors. Therefore, Union does not support to inherit from the Object built-in type.
A Union supports member procedures including Constructor, Destructor, Function, Operator, Property and Sub. All members of a Union are public and access modifiers are not supported.
A Union can also contain nested types or unions, allowing data members to be grouped as desired.
Type and Union can be directly nested on condition of alternating their nesting.
Only the main structure (Type or Union) can be named, the others (nested) must be unnamed.
Nested unnamed Type or Union can not have procedure members or static data members (same restriction for local scope named Type/Union).
A Union can be passed in a similar way of a User Defined Type to overloaded operator procedures.
Note: When Union extends a base, it can be confusing because no new fields are added to the base, but instead the base is added to the derived Union. This means that data elements in the derived Union can share the same memory space like the base (here it doesn't matter whether the base is a Union or not). Of course it can be dangerous, but that is always the problem with Unions.
If only the base is a Union, then it won't be affected by data elements from the derived UDT.
Since Union is not allowed to have complex data elements (i.e. UDTs with constructor/destructor, or dynamic strings), a derived Union can not be allowed to have (contain) a complex base.
The size of the Union is the size of the largest data element.
Since they occupy a common memory space, only one data element can usually be used at a given time (when a given data element is written, the other data elements sharing the common union space may be overwritten or mutilated).
Like Type, Union can use the optional Field = number specifier for field alignment, and supports also inheritance through the use of the Extends keyword.
Unlike Type, Union can not contain variable-length strings and arrays, and more generally can not have object fields (or bases) with constructors or destructors. Therefore, Union does not support to inherit from the Object built-in type.
A Union supports member procedures including Constructor, Destructor, Function, Operator, Property and Sub. All members of a Union are public and access modifiers are not supported.
A Union can also contain nested types or unions, allowing data members to be grouped as desired.
Type and Union can be directly nested on condition of alternating their nesting.
Only the main structure (Type or Union) can be named, the others (nested) must be unnamed.
Nested unnamed Type or Union can not have procedure members or static data members (same restriction for local scope named Type/Union).
A Union can be passed in a similar way of a User Defined Type to overloaded operator procedures.
Note: When Union extends a base, it can be confusing because no new fields are added to the base, but instead the base is added to the derived Union. This means that data elements in the derived Union can share the same memory space like the base (here it doesn't matter whether the base is a Union or not). Of course it can be dangerous, but that is always the problem with Unions.
If only the base is a Union, then it won't be affected by data elements from the derived UDT.
Since Union is not allowed to have complex data elements (i.e. UDTs with constructor/destructor, or dynamic strings), a derived Union can not be allowed to have (contain) a complex base.
Examples:
' Example 0: Little-endianness
' For larger integer values (as the following Ulong data type),
' bytes are arranged in memory in 'little-endian' byte order
' (the least significant byte gets stored first).
Union UDU
ul As Ulong ' 32-bit data type
Type
ub0 As UByte ' 8-bit data type
ub1 As UByte ' 8-bit data type
ub2 As UByte ' 8-bit data type
ub3 As UByte ' 8-bit data type
End Type
End Union
Dim As UDU u
u.ul = &h12345678
Print Hex(u.ul) ' Result: 12345678
Print Hex(u.ub3), Hex(u.ub2), Hex(u.ub1), Hex(u.ub0) ' Result: 12 34 56 78
Sleep
' For larger integer values (as the following Ulong data type),
' bytes are arranged in memory in 'little-endian' byte order
' (the least significant byte gets stored first).
Union UDU
ul As Ulong ' 32-bit data type
Type
ub0 As UByte ' 8-bit data type
ub1 As UByte ' 8-bit data type
ub2 As UByte ' 8-bit data type
ub3 As UByte ' 8-bit data type
End Type
End Union
Dim As UDU u
u.ul = &h12345678
Print Hex(u.ul) ' Result: 12345678
Print Hex(u.ub3), Hex(u.ub2), Hex(u.ub1), Hex(u.ub0) ' Result: 12 34 56 78
Sleep
' Example 1: Only one union member can be relevantly accessed at a time
Union member
username As String * 32
posts As Ulong
End Union
Dim As member userX
userX.username = "Samantha"
userX.posts = 1234
Print userX.username ' value of username corrupted because final value assigned to posts occupies same memory location
' ' (and this is reason that value of posts is displayed well)
Print userX.posts
Print
Dim As member userY
userY.posts = 4321
userY.username = "Alexander"
Print userY.username
Print userY.posts ' value of posts corrupted because final value assigned to username occupies same memory location
' ' (and this is reason that value of username is displayed well)
Print
Sleep
Union member
username As String * 32
posts As Ulong
End Union
Dim As member userX
userX.username = "Samantha"
userX.posts = 1234
Print userX.username ' value of username corrupted because final value assigned to posts occupies same memory location
' ' (and this is reason that value of posts is displayed well)
Print userX.posts
Dim As member userY
userY.posts = 4321
userY.username = "Alexander"
Print userY.username
Print userY.posts ' value of posts corrupted because final value assigned to username occupies same memory location
' ' (and this is reason that value of username is displayed well)
Sleep
' Example 2: Alternative to RGBA keyword and allowing to retrieve elementary colors values
Union BGRA_UNION
colour As ULONG
Type
blue As UByte
green As UByte
red As UByte
Alpha As UByte
End Type
End Union
Dim ubgra As BGRA_UNION
' Setting the individual color values...
ubgra.red = &h33
ubgra.green = &hcc
ubgra.blue = &h66
' We can get a ULONG value
Print Hex(ubgra.colour) ' Result: 33CC66
Print
' Setting a ULONG value...
ubgra.colour = &h228844
' We can get the individual color values
Print Hex(ubgra.red) ' Result: 22
Print Hex(ubgra.green) ' Result: 88
Print Hex(ubgra.blue) ' Result: 44
Print
Sleep
Union BGRA_UNION
colour As ULONG
Type
blue As UByte
green As UByte
red As UByte
Alpha As UByte
End Type
End Union
Dim ubgra As BGRA_UNION
' Setting the individual color values...
ubgra.red = &h33
ubgra.green = &hcc
ubgra.blue = &h66
' We can get a ULONG value
Print Hex(ubgra.colour) ' Result: 33CC66
' Setting a ULONG value...
ubgra.colour = &h228844
' We can get the individual color values
Print Hex(ubgra.red) ' Result: 22
Print Hex(ubgra.green) ' Result: 88
Print Hex(ubgra.blue) ' Result: 44
Sleep
' Example 3.
' Define a simple union.
Union AUnion
a As UByte
b As UInteger
End Union
' Define a composite type with an unnamed union.
Type CompType
s As String * 20
ui As UByte 'Flag to tell us what to use in union.
Union
au As UByte
bu As UInteger
End Union
End Type
' Flags to let us know what to use in union,
' because it's relevant to only use a single element of a union at a given time.
Const IsInteger = 1
Const IsUByte = 2
Dim MyUnion As AUnion
Dim MyComposite As CompType
' Only one field within the union is set, without choice criterion.
MyUnion.a = 128
MyComposite.s = "Type + Union"
MyComposite.ui = IsInteger ' Tells us this is an integer union.
MyComposite.bu = 1500 ' Field set according to the above flag.
Print "Simple Union: ";MyUnion.a
Print MyComposite.s & ": ";
If MyComposite.ui = IsInteger Then
Print MyComposite.bu
ElseIf MyComposite.ui = IsUByte Then
Print MyComposite.au
Else
Print "Unknown Type."
End If
Print
Sleep
' Define a simple union.
Union AUnion
a As UByte
b As UInteger
End Union
' Define a composite type with an unnamed union.
Type CompType
s As String * 20
ui As UByte 'Flag to tell us what to use in union.
Union
au As UByte
bu As UInteger
End Union
End Type
' Flags to let us know what to use in union,
' because it's relevant to only use a single element of a union at a given time.
Const IsInteger = 1
Const IsUByte = 2
Dim MyUnion As AUnion
Dim MyComposite As CompType
' Only one field within the union is set, without choice criterion.
MyUnion.a = 128
MyComposite.s = "Type + Union"
MyComposite.ui = IsInteger ' Tells us this is an integer union.
MyComposite.bu = 1500 ' Field set according to the above flag.
Print "Simple Union: ";MyUnion.a
Print MyComposite.s & ": ";
If MyComposite.ui = IsInteger Then
Print MyComposite.bu
ElseIf MyComposite.ui = IsUByte Then
Print MyComposite.au
Else
Print "Unknown Type."
End If
Sleep
Dialect Differences:
- Object-related features as functions defined inside the Union block are supported only in the -lang fb dialect.
- Not available in the -lang qb dialect unless referenced with the alias __Union.
Differences from QB:
- New to FreeBASIC
See also:
Back to User Defined Types