Structured Types:
Instances of a structured type hold more than one value. Structured types include arrays and records.. A type can have unlimited levels of structuring.
Arrays:
An array represents an indexed collection of elements of the same type (called the base type). Because each element has a unique index, arrays, unlike sets, can meaningfully contain the same value more than once. Arrays can be allocated statically or dynamically.
Static Arrays:
Static arrays have a fixed size or length:
array[indexType1..indexType2] of baseType;
...where each indexType is an ordinal type whose range does not exceed 2GB. Since the indexTypes index the array, the number of elements an array can hold is limited by the product of the sizes of the indexTypes. indexTypes are Integers.
In the simplest case of a one-dimensional array, there is only a single indexType. For example:
var MyArray: array [1..100] of Char;
declares a variable called MyArray that holds an array of 100 character values. Given this declaration, MyArray[3] denotes the third character in MyArray. If you create a static array but don't assign values to all its elements, the unused elements are still allocated and contain random data; they are like uninitialized variables.
A multidimensional array is an array of arrays. For example:
type TMatrix = array[1..10] of array[1..50] of Single;
TMatrix represents an array of 500 real (in this case, Single) values. A variable MyMatrix of type TMatrix can be indexed like this: MyMatrix[2][45].
The standard functions Low and High operate on array type identifiers and variables. They return the low and high bounds of the array's first index type. The standard function Length returns the number of elements in the array's first dimension.
Dynamic Arrays:
Dynamic arrays do not have a fixed size or length. Instead, memory for a dynamic array is reallocated when you assign a value to the array or pass it to the SetLength or SetArrayLength procedure. For example:
var MyFlexibleArray: array of Single;
...declares a one-dimensional dynamic array of singles. The declaration does not allocate memory for MyFlexibleArray. To create the array in memory, call SetLength. For example, given the previous declaration:
SetLength(MyFlexibleArray, 20);
or
SetArrayLength(MyFlexibleArray, 20);
...allocates an array of 20 reals, indexed 0 to 19. Dynamic arrays are always integer-indexed, always starting from 0.
If X and Y are variables of the same dynamic-array type, X := Y points X to the same array as Y (There is no need to allocate memory for X before performing this operation). For example, after this code executes:
scar Code:
var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := A;
B[0] := 2;
end;
the value of A[0] is 2 (If A and B were static arrays, A[0] would still be 1).
Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7) does not reallocate the array. Out-of-range indexes are not reported at compile time.
When dynamic-array variables are compared, their references are compared, not their array values. Thus, after execution of the code:
scar Code:
var
A, B: array of Integer;
begin
SetLength(A, 1);
SetLength(B, 1);
A[0] := 2;
B[0] := 2;
end;
A = B returns False but A[0] = B[0] returns True.
Once a dynamic array has been allocated, you can pass it to the standard functions Length, High, and Low. Length returns the number of elements in the array, High returns the array's highest index (that is, Length - 1), and Low returns 0. In the case of a zero-length array, High returns -1 (with the anomalous consequence that High < Low).
Note: In some function and procedure declarations, array parameters are represented as array of baseType, without any index types specified. For example, function CheckStrings(A: array of String): Boolean;
This indicates that the function operates on all arrays of the specified base type, regardless of their size, how they are indexed, or whether they are allocated statically or dynamically.
Multidimensional Dynamic Arrays:
To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example:
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
...declares a two-dimensional array of strings.
You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example:
var Ints: array of array of Integer;
SetLength(Ints,10);
allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); For example:
SetLength(Ints[2], 5);
makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2][4] := 6.
Records:
A record represents a heterogeneous set of elements. Each element is called a field; the declaration of a record type specifies a name and type for each field. The syntax of a record type declaration is:
scar Code:
type
recordTypeName = record
fieldList1: Integer;
...
fieldListn: String;
end;
where recordTypeName is a valid identifier, each type denotes a type, and each fieldList is a valid identifier or a comma-delimited list of identifiers. The final semicolon is optional.
For example, the following declaration creates a record type called TDateRec:
scar Code:
type
TDateRec = record
Year: Integer;
Month: (Jan, Feb, Mar, Apr, May, Jun,
Jul, Aug, Sep, Oct, Nov, Dec);
Day: String;
end;
Each TDateRec contains three fields: an integer value called Year, a value of an enumerated type called Month, and another integer between 1 and 31 called Day. The identifiers Year, Month, and Day are the field designators for TDateRec, and they behave like variables. The TDateRec type declaration, however, does not allocate any memory for the Year, Month, and Day fields; memory is allocated when you instantiate the record, like this:
var Record1, Record2: TDateRec;
This variable declaration creates two instances of TDateRec, called Record1 and Record2.
You can access the fields of a record by qualifying the field designators with the record's name:
scar Code:
Record1.Year := 1904;
Record1.Month := Jun;
Record1.Day := 16;
Or use a with statement:
scar Code:
with Record1 do
begin
Year := 1904;
Month := Jun;
Day := 16;
end;
You can now copy the values of Record1's fields to Record2:
Record2 := Record1;
Instead of defining record types, you can use the record construction directly in variable declarations:
scar Code:
var S: record
Name: string;
Age: Integer;
end;
However, a declaration like this largely defeats the purpose of records, which is to avoid repetitive coding of similar groups of variables. Moreover, separately declared records of this kind will not be assignment-compatible, even if their structures are identical.