0% found this document useful (0 votes)
6 views

Extra 1

Uploaded by

skamelrech2020
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Extra 1

Uploaded by

skamelrech2020
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

122 - 05: Arrays and Records

the loop when the array size changes. Low and High make your code easier to main-
tain and more reliable.

note Incidentally, there is no run-time overhead for using Low and High with static arrays. They are
resolved at compile-time into constant expressions, not actual function calls. This compile-time
resolution of expressions and function calls also happens for many other system functions.

Another relevant function is Length, which returns the number of elements of the
array. I've combined these three functions in the following code that computes and
displays the average temperature for the day:
var
I: Integer;
Total: Integer;
begin
Total := 0;
for I := Low(DayTemp1) to High(DayTemp1) do
Inc (Total, DayTemp1[I]);
Show ((Total / Length(DayTemp1)).ToString);
This code is also part of the ArraysTest application project.

Multi-Dimensional Static Arrays


An array can have more than one dimension, expressing a matrix or a cube rather
than a list. Here are two sample definitions:
type
TAllMonthTemps = array [1..24, 1..31] of Integer;
TAllYearTemps = array [1..24, 1..31, 1..12] of Integer;
You can access an element as:
var
AllMonth1: TAllMonthTemps;
AllYear1: TAllYearTemps;
begin
AllMonth1 [13, 30] := 55; // hour, day
AllYear1 [13, 30, 8] := 55; // hour, day, month

note Static arrays immediately take up a lot of memory (in the case above on the stack), which should
be avoided. The AllYear1 variable requires 8,928 Integers, taking up 4 bytes each, that is almost
35KB. Allocating such a large block in the global memory or on the stack (as in the demo code) is
really a mistake. A dynamic array, instead, uses the heap memory, and offers much more flexibil-
ity in terms of memory allocation and management.

Given these two array types are built on the same core types, you should better
declare them using the preceding data types, as in the following code:

Marco Cantù, Object Pascal Handbook


05: Arrays and Records - 123

type
TMonthTemps = array [1..31] of TDayTemperatures;
TYearTemps = array [1..12] of TMonthTemps;
This declaration inverts the order of the indexes as presented above, but it also
allows assignment of whole blocks between variables. Let's see how you can assign
individual values:
Month1 [30][14] := 44;
Month1 [30, 13] := 55; // day, hour
Year1 [8, 30, 13] := 55; // month, day, hour
In theory, you should use the first line, selecting one of the array of arrays, and then
an element of the resulting array. However, the version with the two indexes within
square brackets is also allowed. Or with three indexes, in the “cube” example.
The importance of using intermediate types lies on the fact that arrays are type com-
patible only if they refer to the same exact type name (that is exactly the same type
definition) not if their type definitions happen to refer to the same implementation.
This type compatibility rule is the same for all types in the Object Pascal, with only
some specific exceptions.
For example, the following statement copies a months's temperatures to the third
month of the year:
Year1[3] := Month1;
Instead, a similar statement based on the stand alone array definitions (which are
not type compatible):
AllYear1[3] := AllMonth1;
would cause the error:
Error: Incompatible types: 'array[1..31] of array[1..12] of Integer'
and 'TAllMonthTemps'
As I mentioned, static arrays suffer memory management issues, specifically when
you want to pass them as parameters or allocate only a portion of a large array.
Moreover, you cannot resize them during the lifetime of the array variable. This is
why is is preferable to use dynamic arrays, even if they require a little extra manage-
ment, for example regarding memory allocation.

Dynamic Arrays
In the traditional Pascal language arrays had a fixed-size arrays and you specified
the number of elements of the array as you declared the data type. Object Pascal
supports also a direct and native implementation of dynamic arrays.

Marco Cantù, Object Pascal Handbook


124 - 05: Arrays and Records

note “Direct implementation of dynamic arrays” here is in contrast to using pointers and dynamic
memory allocation to obtain a similar effect... with very complex and error-prone code.

Dynamic arrays are dynamically allocated and reference counted (making parameter
passing much faster, as only the reference is passed, and not a copy of the complete
array). When you are done, you can clear an array by setting its variable to nil or its
length to zero, but given they are reference counted in most cases the compiler will
automatically free the memory for you.
With a dynamic array, you declare an array type without specifying the number of
elements and then allocate it with a given size using the SetLength procedure:
var
Array1: array of Integer;
begin
// this would cause a runtime Range Check error
// Array1 [1] := 100;
SetLength (Array1, 10);
Array1 [1] := 100; // this is OK
You cannot use the array until you've assigned its length, allocating the required
memory on the heap. If you do so, you'd either see a Range Check error (if the corre-
sponding compiler option is active) or an Access Violation (on Windows) or similar
memory access error on another platform. The SetLength call sets all the values to
zero. The initialization code makes it possible to start reading and writing values of
the array right away, without any fear of memory errors (unless you violate the array
boundaries).
If you do need to allocate memory explicitly, you don't need to free it directly. In the
code snippet above, as the code terminates and the Array1 variable goes out of
scope, the compiler will automatically free its memory (in this case the ten integers
that have been allocated). So while you can assign a dynamic array variable to nil or
call SetLength with 0 value, this is generally not needed (and rarely done).
Notice that the SetLength procedure can also be used to resize an array, without los-
ing its current content (if you are growing it) but you would lose some elements (if
you are shrinking it). As in the initial SetLength call you indicate only the number of
elements of the array, the index of a dynamic array invariably starts from 0 and goes
up to the number of elements minus 1. In other words, dynamic arrays don't support
two features of classic static Pascal arrays, the non-zero low bound and the non-inte-
ger indexes. At the same time, they match more closely how arrays work in most
languages based on the C syntax.
Just like static arrays, to know about the current size of a dynamic array, you can use
the Length, High, and Low functions. For dynamic arrays, however, Low always
returns 0, and High always returns the length minus one. This implies that for an

Marco Cantù, Object Pascal Handbook


05: Arrays and Records - 125

empty array High returns -1 (which, when you think about it, is a strange value, as it
is lower than that returned by Low).
So, as an example, in the DynArray application project I've populated and extracted
the information from a dynamic array using adaptable loops. This is the type and
variable definition:
type
TIntegersArray = array of Integer;

var
IntArray1: TIntegersArray;
The array is allocated and populated with values matching the index, using the fol-
lowing loop:
var
I: Integer;
begin
SetLength (IntArray1, 20);
for I := Low (IntArray1) to High (IntArray1) do
IntArray1 [I] := I;
end;
A second button has the code both to display each value and compute the average,
similar to that of the previous example but in a single loop:
var
I: Integer;
total: Integer;
begin
Total := 0;
for I := Low(IntArray1) to High(IntArray1) do
begin
Inc (Total, IntArray1[I]);
Show (I.ToString + ': ' + IntArray1[I].ToString);
end;
Show ('Average: ' + (Total / Length(IntArray1)).ToString);
end;
The output of this code is quite obvious (and mostly omitted):
0: 0
1: 1
2: 2
3: 3
...
17: 17
18: 18
19: 19
Average: 9.5
Beside Length, SetLength, Low, and High, there are also other common procedures
that you can use on arrays, such as the Copy function, you can use to copy a portion
of an array (or all of it). Notice that you can also assign an array from a variable to

Marco Cantù, Object Pascal Handbook

You might also like