UNION/END UNION statements

Purpose

Create a new User-Defined Type definition whose member elements overlap in memory.

Syntax

UNION UnionName

   MemberName [(subscripts)] AS TypeName

  [MemberName [(subscripts)] AS TypeName]

  [...]

END UNION

Remarks

A union is a type - very similar to a User-Defined Type - except that its elements overlap in memory.  While this may seem strange at first, it has enormous potential.

For example, say you are designing an accounting program.  You want to make it general purpose so it has widespread appeal.  But everyone does their accounting differently; for example, some people use account numbers that are plain Integers, while others may use alphanumeric account names.  Using a Union makes this easy.  Another common use of a Union is variable type conversion.  The is best described by way of an example:

UNION VarConvert

  iLong  AS LONG

  iDword AS DWORD

  sStr   AS STRING * 4

END UNION

 

DIM x AS VarConvert, y AS DWORD, z AS STRING

x.iLong = 123456&

y       = x.iDword

z       = x.sStr

Like a User-Defined Type, a Union may also contain arrays, and these follow the same rules as User-Defined Type member arrays (see Type Members for syntax rules and additional examples).  The following example demonstrates the use of a Union member array:

UNION Arrs

  a1(1 TO 1024) AS BYTE

  st AS ASCIIZ * 10

END UNION

 

FUNCTION PBMAIN

    DIM a AS Arrs

    a.a1(1) = 72

    a.a1(2) = 101

    a.a1(3) = 108

    a.a1(4) = 108

    a.a1(5) = 111

    a.a1(6) = 33

    ' At this point, a.st contains "Hello!"

END FUNCTION

Bit Variables

UNION structures may contain bit variables, which are named BIT (unsigned values) or SBIT (signed values).  Each bit variable may occupy from 1 to 31 bits, and they may be packed one after another up to a total of 32 bits per bit field.  The size of a bit variable is defined as follows:

var AS BIT * nlit [IN BYTE|WORD|DWORD]

…where the term "* nlit" defines the number of bits (1 to 31), and the optional term "IN BYTE|WORD|DWORD", if present, defines the start of a new bit field of 1, 2, or 4 bytes.  For example:

UNION ABCDE

  Odd1 AS BIT * 1 IN DWORD

  Value1 AS LONG

END UNION

The example UNION structure above is 4 bytes in size, containing a 1-byte bit field and a 4-byte LONG.

UNION abcde

  Part1 AS BIT * 8 IN DWORD

  Part2 AS BIT * 16

END UNION

The example union above is 4 bytes in size, containing an 8-bit field and an overlapping 16-bit field.

Structures within structures

Structures (TYPE/UNION) may be embedded within another structure, for simplification in referencing deeply nested items, by simply stating the structure name alone at the appropriate position.  The internal alignment of the member structure is precisely maintained regardless of other alignment specifications, to foster inheritance issues.  For example:

TYPE ABCD3   

A AS LONG    

ABCD2

C AS LONG    

END TYPE  

TYPE ABCD2     

D AS DWORD    

E AS DOUBLE   

ABCD1         

END TYPE  

UNION ABCD1

F AS DWORD

G AS LONG

H AS SINGLE

END UNION

In this case, you could access the lone Single-precision float member of this structure very simply.  Assuming DIM X AS ABCD3, you could reference the Single-precision Union member with the variable name X.H, instead of the extended syntax X.ABCD2.ABCD1.H

Restrictions

A Union can contain elements of dissimilar sizes.  The size of a Union structure is always determined by the longest member element.  This is usually an important consideration when using a Union within another Union or UDT structure, in order to determine the size of the final structure.

For related information, please refer to the TYPE/END TYPE, User-Defined Types and Unions sections.

Field strings cannot be used in UDT or UNION structures.  Attempting to do so results in a compile-time Error 485 ("Dynamic/Field strings not allowed").

See also

DIM, LEN, LET (with Types), SIZEOF, TYPE/END TYPE, User-Defined TypesUnions

Example

UNION AccountUnion

  AccountNumber  AS LONG

  AccountName    AS STRING * 16

END UNION

 

TYPE JournalEntryType

  Account  AS AccountUnion

  Amount   AS CUR

END TYPE

 

DIM JournalEntry AS JournalEntryType

 

JournalEntry.Account.AccountName = "Smith"

JournalEntry.Amount = 123.01@

...

JournalEntry.Account.AccountNumber = 1001

JournalEntry.Amount = -1.99@