4.36 Unions


4.36 Unions

A record definition assigns different offsets to each field in the record according to the size of those fields. This behavior is quite similar to the allocation of memory offsets in a var or static section. HLA provides a second type of structure declaration, the union, that does not assign different addresses to each object; instead, each field in a union declaration has the same offset — zero. The following example demonstrates the syntax for a union declaration:

 type      unionType:           union                << fields (syntactically identical to record declarations) >>           endunion; 

You access the fields of a union exactly the same way you access the fields of a record: using dot notation and field names. The following is a concrete example of a union type declaration and a variable of the union type:

 type      numeric:           union                i: int32;                u: uns32;                r: real64;           endunion;                .                .                . static      number: numeric;                .                .                .      mov( 55, number.u );                .                .                .      mov( -5, number.i );                .                .                .      stdout.put( "Real value = ", number.r, nl ); 

The important thing to note about union objects is that all the fields of a union have the same offset in the structure. In the example above, the number.u, number.i, and number.r fields all have the same offset: zero. Therefore, the fields of a union overlap in memory; this is very similar to the way the 80x86 8-, 16-, and 32-bit registers overlap one another. Usually, access to the fields of a union are mutually exclusive; that is, you do not manipulate separate fields of a particular union variable concurrently because writing to one field overwrites the other fields. In the example above, any modification of number.u would also change number.i and number.r.

Programmers typically use unions for two different reasons: to conserve memory or to create aliases. Memory conservation is the intended use of this data structure facility. To see how this works, let's compare the numeric union above with a corresponding record type:

 type      numericRec:           record                i: int32;                u: uns32;                r: real64;           endrecord; 

If you declare a variable, say n, of type numericRec, you access the fields as n.i, n.u, and n.r exactly as though you had declared the variable to be type numeric. The difference between the two is that numericRec variables allocate separate storage for each field of the record, while numeric objects allocate the same storage for all fields. Therefore, @size(numericRec) is 16 because the record contains two double word fields and a quad word (real64) field. @size(numeric), however, is eight. This is because all the fields of a union occupy the same memory locations, and the size of a union object is the size of the largest field of that object (see Figure 4-11).

click to expand
Figure 4-11: Layout of a UNION vs. a RECORD Variable.

In addition to conserving memory, programmers often use unions to create aliases in their code. As you may recall, an alias is a different name for the same memory object. Aliases are often a source of confusion in a program so you should use them sparingly; sometimes, however, using an alias can be quite convenient. For example, in some section of your program you might need to constantly use type coercion to refer to an object using a different type. Although you can use an HLA text constant to simplify this process, another way to do this is to use a union variable with the fields representing the different types you want to use for the object. As an example, consider the following code:

 type      CharOrUns:           union                c:char;                u:uns32;           endrecord; static      v:CharOrUns; 

With a declaration like the above, you can manipulate an uns32 object by accessing v.u. If, at some point, you need to treat the L.O. byte of this uns32 variable as a character, you can do so by simply accessing the v.c variable, e.g.,

      mov( eax, v.u );      stdout.put( "v, as a character, is '", v.c, "'" nl ); 

You can use unions exactly the same way you use records in an HLA program. In particular, union declarations may appear as fields in records, record declarations may appear as fields in unions, array declarations may appear within unions, you can create arrays of unions, and so on.




The Art of Assembly Language
The Art of Assembly Language
ISBN: 1593272073
EAN: 2147483647
Year: 2005
Pages: 246
Authors: Randall Hyde

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net