See Also: Declaring Variables: Array Declarations, Move, Struct Type, Struct Variables, Struct Declaration, Struct Variable Assignments, Struct Properties, SizeOfType


Declares a new structured data type.


Struct {type-name}

    {data-type} {member-name}

    [{data-type} {member-name}]




Struct {type-name}

    [ {Name={alternate-member-name} } ]

    {data-type} {member-name}

    [{data-type} {member-name}]




What It Does

A struct represents a set of elements where each element is called a member.  A struct type declaration defines a particular set of elements and associates it with a new type identifier.

Once a struct type is declared it can be used just like any other DataFlex data type. i.e. you may declare and use variables and properties, and you may declare procedure or function parameters and return types of a struct type. For example…

Struct tCreditCard    // declares a new struct type

    Integer iType

    String  sName

    Integer iNumber

    Date    dExpires



tCreditCard MyCreditCard  // declares a new variable of tCreditCard type

Members of a struct variable are accessed using the member access operator (the dot operator). For example…

Move 0                to MyCreditCard.iType

Move "Joe Bloggs"     to MyCreditCard.sName

Move 1234123412341234 to MyCreditCard.iNumber


Date dToday

Sysdate dToday


If (MyCreditCard.dExpires >= dToday) Showln "Expired!"

For each struct type defined, the compiler automatically defines the symbol _struct_{name} where {name} is replaced with the name of the struct type. This can be used at compile time to determine whether a particular struct type has been defined. For example:

#IFDEF _struct_tCreditCard

    // Do something special if the tCreditCard struct type has been defined



For more information refer to struct types in the Language Guide.

Struct Alignment

Structure alignment (or structure padding) happens when structs are passed to other DLLs or Windows functions. This is because the compiler ensures that each struct instance will have the alignment of its widest scalar member (for performance reasons) and extra memory space may be inserted within the struct (unless structure alignment is explicitly switched off in the DLL).

DataFlex does not do structure alignment. This means that you might have to add extra padding items yourself to exposed Windows structs. This issue is especially relevant to the 64-bit platform. Take this example:

Struct tWinChooseFont

  DWord lStructSize

  Handle hwndOwner


In 32-bit, both DWord and Handle are 32-bit items (4 bytes), which does not lead to any padding. However, in 64-bit, Handle has become 64-bit (8 bytes) and that causes the struct to have 8-byte alignment, which means that in Windows compilers there will be 4 bytes of space inserted after lStructSize. If this doesn’t get corrected in 64-bit environments, there can be an unexpected runtime error or crash upon calling the external function. The solution in DataFlex code is:

Struct tWinChooseFont

  DWord lStructSize


  Integer iStructAlignment


  Handle hwndOwner


Be aware that such changes might influence code where you do a SizeOfType() on that struct.

The structure alignment issue is not relevant to structs internal to your application (not passed to outside DLLs) or structs in COM class interfaces.


The following example demonstrates a nested struct declaration. i.e. a struct type with a member that is also a struct type.

Struct tAddress

    String Street

    String City

    String State

    Integer Zip



Struct tCompany

    String   Name

    tAddress PostalAddress

    tAddress Location

    Integer  Phone


The following example declares a struct variable named tStudent, then creates a dynamic array of type tStudent named myStudents. Next, a loop is created that finds Student records and fills the array with the information from the database.

// declare data type tStudent

Struct tStudent

    String FirstName

    String LastName

    String ClassName

    Integer LastTestScore



tStudent[] myStudents  // dynamic array of tStudent


open Student  // open Student table


integer i

for i from 0 to iNumberOfStudents

    clear Student

    move i to Student.Id

    find eq Student by 1  // Id

    if (Found) begin

        move Student.First     to myStudents[i].FirstName

        move Student.Last      to myStudents[i].LastName

        move Student.Class     to myStudents[i].ClassName

        move Student.TestScore to myStudents[i].LastTestScore




Initializing struct variable members:

In the example below, move is used to initialize members of the myBillingAddress struct variable.

struct tUSAddress

    string sFirstName

    string sLastName

    string sAddressLine1

    string sAddressLine2

    string sCity

    string sState

    integer iZipCode



Procedure CreateBillingAddress

    tUSAddress myBillingAddress


    // initialize myBillingAddress

    move "John"                  to myBillingAddress.sFirstName

    move "Smith"                 to myBillingAddress.sLastName

    move "Data Access Worldwide" to myBillingAddress.sAddressLine1

    move "14000 SW 119 Ave"      to myBillingAddress.sAddressLine2

    move "Miami"                 to myBillingAddress.sCity

    move "FL"                    to myBillingAddress.sState

    move "33186"                 to myBillingAddress.iZipCode



Copying struct variable members:

Assume that the example below is a continuation of the sample above, using the same struct declaration for tUSAddress. Here, move is used to copy the value of myBillingAddress to myShippingAddress. Using move to copy struct variables uses a deep memberwise copy operation to copy each struct variable member value from the first struct variable to the second struct variable.

Procedure CreateShippingAddress tUSAddress myBillingAddress

    tUSAddress myShippingAddress


    move myBillingAddress to myShippingAddress


Re-initializing struct variable members:

There is a quick way to re-initialize array variables to their original (blank) values. Simply move an un-initialized array variable of the same type:

Struct tTest

    Integer iTest

    String sTest



Procedure Test

    tTest localTest blankTest


    // initialize localTest with values

    Move 104 to localTest.iTest

    Move "Fred" to localTest.sTest


    // re-initialize localTest elements to their original (blank) values

    Move blankTest to localTest


The same can be done with struct properties:

Property tTest pMyTest


Procedure ReinitializepMyTest

    tTest blankTest


    Set pMyTest to blankTest



Struct tContact

    String Company

    String[5] ContactNames

    Integer Fax


However the following declaration will produce a compile-time error.

Integer icNames

Move 5 to icNames


Struct tContact

    String Company

    String[icNames] ContactNames

    Integer Fax


This restriction does not apply to dynamic or jagged array struct members.