Navigation:  Tutorial >

Using unions with gwst structures

Previous pageReturn to chapter overviewNext page

All members of a union will start at the same location in memory, this mean that when you assign a value to a union member you are overwriting partial or totally the rest of the members of the union.

 

There are 2 common usages of unions. The first is to reuse the same portion of memory to store values of different types at different times. The second usage is to got different interpretations of the same portion of memory.

 

See the following code:

BEGIN STRUCTURE stWORD

   MEMBER BYTE nLoByte

   MEMBER BYTE nHiByte

END STRUCTURE

 

We have defined a structure called stWORD that allow to access the low and high bytes of a 16 bit unsigned integer value

 

We want to access the low and high words of a 32 bits unsigned value, but also we want to access individual bytes of any of the WORD parts.

 

BEGIN STRUCTURE stDWORD

   BEGIN UNION

      MEMBER   WORD    nLoWord

      MEMBER @ stWORD  LoWord

   END UNION

   BEGIN UNION

      MEMBER   WORD    nHiWord

      MEMBER @ stWORD  HiWord

   END UNION

END STRUCTURE

 

Now we can assign or retrieve values in this way

oDw := stDWORD():New()

oDw:nLoWord := 65535

? oDw:LoWord:nLoByte // 255

 

But we have a little trouble, we want to access also to our 32 bit value as a single 32 bit integer value. ot4xb not provide direct support for nested unnamed unions, but a small set of commands that allow to do it manually with a high level of flexibility.

 

BEGIN STRUCTURE stWORD

   MEMBER w

   GWSTSETOFFSET(0) // Next member will start at the begining of the structure

   MEMBER BYTE nLoByte

   MEMBER BYTE nHiByte

END STRUCTURE

// --------------------------------------------------------------------------

BEGIN STRUCTURE stDWORD

   MEMBER dw

   GWSTSETOFFSET(0) // Next member will start at the begining of the structure

   MEMBER   WORD    nLoWord

   MEMBER   WORD    nHiWord

   GWSTSETOFFSET(0) // Next member will start at the begining of the structure

   MEMBER @ stWORD  LoWord

   MEMBER @ stWORD  HiWord

END STRUCTURE

In the above example have used blocks of the same size, so we was not have the need to take care of the final size of the structure, but with more complex definitions we need to be sure that any previous member surpass the total size of the structure.

 

BEGIN STRUCTURE stWORD local nMax,nBase

 

You can include some local declarations to use within your dynamic class function that will hold your structure definition.

 

   nMax := nBase := GWSTGETOFFSET()

 

Store the current offset as the base and max offset, before add more members

 

      MEMBER w

   nMax := Max(GWSTGETOFFSET(),nMax);GWSTSETOFFSET(nBase)

 

Store the max offset reached by the union members and return to the base

 

      MEMBER BYTE nLoByte

      MEMBER BYTE nHiByte

 

Again check if the maximum offset was reached and adjust the size of the structure to the largest block at the end of the last union level.

 

   nMax := Max(GWSTGETOFFSET(),nMax);GWSTSETOFFSET(nMax)

END STRUCTURE

 

A common usage of unions with ot4xb is the possibility of  view the signed and unsigned representation of the same internal value, for this purpose ot4xb provides a command that go back to the offset previous to the last defined member.

 

BEGIN STRUCTURE MyStruct

   MEMBER LONG      sl

   GWSTBACK 

   MEMBER U_INT32   ul

END STRUCTURE

// -----------------------------

o := MyStruct():New()

o:sl := -1

? o:sl  // -1

? o:ul  // 4294967295