5.2.1 Declaring Structure and Union Types

When you declare a structure or union type, you create a template for data that contains the sizes and, optionally, the initial values for fields in the structure or union but that allocates no memory.

The STRUCT keyword marks the beginning of a type declaration for a structure. (STRUCT and STRUC are synonyms.) STRUCT and UNION type declarations have the following format:

name {STRUCT | UNION} [[alignment]] [[,NONUNIQUE ]]
fielddeclarations
name ENDS

The fielddeclarations are a series of one or more variable declarations. You can declare default initial values individually or with the DUP operator (see Section 5.2.2, “Defining Structure and Union Variables”). Section 5.2.3, “Referencing Structures, Unions, and Fields,” explains the NONUNIQUE keyword. Structures and unions can also be nested in MASM 6.0 (see Section 5.2.4).

Initializing Fields

If you provide initializers for the fields of a structure or union when you declare the type, these initializers become the default value for the fields when you define a variable of that type. Section 5.2.2 explains default initializers.

When you initialize the fields of a union type, the type and value of the first field become the default value and type for the union. In this example of an initialized union declaration, the default type for the union is DWORD:

DWB UNION

d DWORD 00FFh

w WORD ?

b BYTE ?

DWB ENDS

If the size of the first member is less than the size of the union, the assembler initializes the rest of the union to zeros. When initializing strings in a type, make sure the initial values are long enough to accommodate the largest possible string.

Field Names

Structure and union field names in MASM 6.0 must be unique within a given nesting level because they represent the offset from the beginning of the structure to the corresponding field.

Summary: A nested structure has its own level.

In MASM 6.0, a label and a structure field may have the same name, but not a text macro and a field name. Also, field names between structures need not be unique. Field names do need to be unique if you place OPTION M510 or OPTION OLDSTRUCTS in your code or use the /Zm option from the command line, since versions of MASM prior to 6.0 require unique field names (see Appendix A).

Alignment Value and Offsets for Structures

Data access to structures is faster on aligned fields than on unaligned fields. Therefore, alignment gains speed at the cost of space. Alignment improves access on 16-bit processors but makes no difference on code executing on an 8-bit 8088 processor.

The way the assembler aligns structure fields determines the amount of space required to store a variable of that type. Each field in a structure has an offset relative to 0. If you specify an alignment in the structure declaration (or with the /Zpn command-line option), the offset for each field may be modified by the alignment (or n).

The only values accepted for alignment are 1, 2, and 4. The default is 1. If the type declaration includes an alignment, the fields are aligned to the minimum of the field's size and the alignment. Any padding required to reach the correct offset for the field is added prior to allocating the field. The padding consists of zeros and always precedes the field.

If the number of bytes in the field is greater than the alignment value, the element will be padded such that the offset of the element is divisible by the alignment value. If the number of bytes is greater than or equal to the alignment value, the offset of the element is padded such that it is divisible by the element size.

The size of the structure must also be evenly divisible by the structure alignment value, so zeros may be added at the end of the structure.

If neither the alignment nor the /Zp command-line option is used, the offset is incremented by the size of each data directive. This is the same as a default alignment equal to 1. The alignment specified in the type declaration overrides the /Zp command-line option.

These examples show how offsets are determined:

STUDENT2 STRUCT 2 ; Alignment value is 2

score WORD 1 ; Offset is 0

id BYTE 2 ; Offset is 2

year DWORD 3 ; Offset is 4; one byte padding added

sname BYTE 4 ; Offset is 8

STUDENT2 ENDS

One byte of padding is added at the end of the first byte-sized field. Otherwise the offset of the year field would be 3, which is not divisible by the alignment value of 2. The size of this structure is now 9 bytes. Since 9 is not evenly divisible by 2, one byte of padding is added at the end of student2.

STUDENT4 STRUCT 4 ; Alignment value is 4

sname BYTE 1 ; Offset is 0

score WORD 10 DUP (100) ; Offset is 2

year BYTE 2 ; Offset is 22; 1 byte padding

; added so offset of next field

; is divisible by 4

id DWORD 3 ; Offset is 24

STUDENT4 ENDS

Summary: The alignment value affects memory allocation of structure variables.

The alignment value affects the alignment of structure variables, so adding an alignment value affects memory usage. This feature provides compatibility with structures in Microsoft C.

With MASM 6.0, C programmers can use the H2INC utility to translate C structures to MASM (see Chapter 16).