Arrays¶
Overview¶
The Sedona Framework model for arrays is very similar to the C language. An array is just a block of memory large enough hold a declared number of items. Arrays do not store their own length, so bounds checking is up to the developer.
The format of an array type declaration is:
<Type>[<size>] // size is optional
byte[10] buf // example of sized array type declaration
Person[] people // example of unsized array type declaration
If the size of the array is specified between the brackets we call it a sized array, otherwise we call it a unsized array. The Sedona Framework does not support multi-dimensional arrays.
Memory Management¶
Arrays are always passed by reference - the reference is just a pointer to the base address of the array. To actually allocate memory for an array, it must be declared as an inline field. For example:
class Foo
{
static int[5] x
static inline int[5] y
}
In the class above we declare two static fields. The field x
is a
reference to an array of five ints - so it allocates enough memory to
store a pointer (typically 4 bytes on a 32-bit machine). The field y
on the other hand is storage for five ints, so it allocates 20 bytes.
In the example above Foo.x
is just a pointer, so you can set x
to
any value that points to 5 ints. For example the assignment x=y
updates x
to point to the block of memory allocated by y
.
On the other hand, y
actually allocates a block of memory to store 5
ints. You can pass y
around as a pointer and index its values, but you
cannot change what it points to. Like all inline fields, y
can never
be used as the left hand side of an assignment statement.
Arrays of References¶
An array of objects is stored as an array of references to those objects. On a machine with 32-bit pointers, this means that an array of 3 objects will always be 12 bytes no matter how big the objects themselves are. However, there is a special syntax for allocating enough memory to hold the objects too:
class Point
{
int x
int y
}
class Shape
{
static Point[] a
static inline Point[3] b
static inline Point[3] c = {...}
}
The Point
class stores two ints, which means a single instance of
Point is 8 bytes. Note the three different field declarations in
Shape
:
- Shape.a: The first field
a
declares a pointer to an array ofPoint
s, soa
is allocated enough memory to store a single pointer (most likely 4 bytes). - Shape.b: The field
Point.b
allocates enough memory to store 3 references to Points, but doesn't allocate any memory for actualPoint
instances - sob
would allocate 12 bytes on a 32-bit machine. The references don't point to anything yet; they must be initialized elsewhere to point to actual objects. - Shape.c: The
Point.c
field uses the special syntax= {...}
to allocate enough memory for an array of 3 references to Points and 3 instances of Points. Soc
will allocate 36 bytes of memory on a 32-bit machine: 12 for the array itself, plus 3*8 for the instances. The compiler auto-generates initialization code to assign the references to the instances.
Unsized Classes¶
Under most circumstances you must specify a size to declare an inline array. However a class may declare one instance field as an unsized inline array. We call these classes unsized classes because their size isn't fixed. To make this work, unsized classes have a few special rules:
- The class can have no more than one unsized inline array
- The unsized inline array must be an instance field (not static)
- The array length must be assigned in the constructor
- The length must be assigned directly from a constructor parameter
- The class must be declared
final
(true of all classes with constructor arguments)
The sys::Buf
class is a good example of an unsized class:
final class Buf
{
Buf(int maxBufLen)
{
this.bytesLen = maxBufLen
this.bytes.length = maxBufLen
}
inline byte[] bytes // raw byte array
short bytesLen // length of bytes array
}
The code snippet above illustrates how to declare an unsized inline array. The constructor must have a statement that assigns the "length field" of the array. The right hand side of the assignment must be a parameter of the constructor (it can't be a calculated value).
To declare an instance of a Buf
we pass the length to the inline
constructor:
inline Buf(3) buf1st
inline Buf(10) buf2nd
In the example above we declared two instances of Buf
. The first
buffer allocates enough memory to store Buf
's fixed slots (such as
bytesLen
) plus enough memory for 3 bytes. The second buffer allocates
enough memory for Buf
's fixed slots plus 10 bytes. This feature is
used extensively when working with the sys::Str
class.
Array Literals¶
Some array types may be declared as literals in code:
define Str[] colors = {"red", "green", "blue"}
See Array Literals for more details.