Arrays
Arrays have a central role in programming. C3 offers built-in arrays, slices and vectors. The standard library enhances this further with dynamically sized arrays and other collections.
Fixed Size 1D Arrays
These are declared as <type>[<size>]
, e.g. int[4]
. Fixed arrays are treated as values and will be copied if given as parameter. Unlike C, the number is part of its type. Taking a pointer to a fixed array will create a pointer to a fixed array, e.g. int[4]*
.
Unlike C, fixed arrays do not decay into pointers. Instead, an int[4]*
may be implicitly converted into an int*
.
When you want to initialize a fixed array without specifying the size, use the [*] array syntax:
Slice
The final type is the slice <type>[]
e.g. int[]
. A slice is a view into either a fixed or variable array. Internally it is represented as a struct containing a pointer and a size. Both fixed and variable arrays may be converted into slices, and slices may be implicitly converted to pointers.
Slicing Arrays
It’s possible to use the range syntax to create slices from pointers, arrays, and other slices.
This is written arr[<start-index> .. <end-index>]
, where the end-index
is inclusive.
You can also use the arr[<start-index> : <slice-length>]
It’s possible to omit the first and last indices of a range:
arr[..<end-index>]
Omitting thestart-index
will default it to 0arr[<start-index>..]
Omitting theend-index
will assign it toarr.len-1
(this is not allowed on pointers)
Equivalently with index offset arr[:<slice-length>]
you can omit the start-index
The following are all equivalent and slice the whole array
You can also slice in reverse from the end with ^i
where the index is len-i
for example:
^1
meanslen-1
^2
meanslen-2
^3
meanslen-3
Again, this is not allowed for pointers since the length is unknown.
One may also assign to slices:
Or copy slices to slices:
Copying between two overlapping ranges, e.g. a[1..2] = a[0..1]
is unspecified behaviour.
Conversion List
int[4] | int[] | int[4]* | int* | |
---|---|---|---|---|
int[4] | copy | - | - | - |
int[] | - | assign | assign | - |
int[4]* | - | cast | assign | cast |
int* | - | assign | assign | assign |
Note that all casts above are inherently unsafe and will only work if the type cast is indeed compatible.
For example:
Internals
Internally the layout of a slice is guaranteed to be struct { <type>* ptr; usz len; }
.
There is a built-in struct std::core::runtime::SliceRaw
which
has the exact data layout of the fat array pointers. It is defined to be
Iteration Over Arrays
Foreach element by copy
You may iterate over slices, arrays and vectors using foreach (Type x : array)
.
Using compile-time type inference this can be abbreviated
to foreach (x : array)
for example:
Foreach element by reference
Using &
it is possible to get an element by reference rather than by copy.
Providing two variables to foreach
, the first is assumed to be the index and the second the value:
Foreach_r reverse iterating
With foreach_r
arrays or slices can be iterated over in reverse order
Iteration Over Array-Like types
It is possible to enable foreach on any custom type
by implementing .len
and []
methods and annotating them using the @operator
attribute:
For more information, see operator overloading
Dynamic Arrays and Lists
The standard library offers dynamic arrays and other collections in the std::collections
module.
Fixed Size Multi-Dimensional Arrays
To declare two dimensional fixed arrays as <type>[<x-size>, <y-size>] arr
, like int[4][2] arr
. Below you can see how this compares to C: