Arrays may be declared and accessed using a conventional square-bracket notation. However, there is a great deal of flexibility in the details of the notation. The required dimensions may be listed after the type name, or after the object name, or any combination of the two. These declarations, for example, are all equivalent:

int[3][4][5] a;  // form 1
int[3][4] a[5];
int[3] a[4][5];
int a[3][4][5];  // form 2

This follows Java usage, which is a superset of C usage (C supports only form 2). Of the different possibilities, form 1 is preferred, since it is the only option when declaring a function which returns an array, and since it makes it obvious that the dimensionality is a property of the type, rather than the object. An array of objects of type X, of dimensionality D, has type "array D of X".

It is often inconvenient and verbose to repeat the bracket notation when handling arrays with several dimensions, so an alternative comma-separated notation is also supported (in common with Algol-derived languages):

int a[3,4,5];    // form 2
a[0][0][0] = 1;  // Ok; C-style
a[0,0,1]   = 2;  // Ok; Algol-style
a[0][0,2]  = 3;  // error: cannot mix the 2 styles in the same expression

Arrays may be passed to, and returned from, functions. Arrays which are assignment-compatible support a number of operations, including assignment and comparison; for example:

main() {
   int  [3,4,5] a;   // an array of default-sized ints
   int  [4,5]   b;
   var32[5]     c;   // an array of var32
   bit7 [5]     d;   // an array of bit7

   a[0] = b;         // Ok
   b = a[1];         // Ok
   c = a[0,0];       // Ok; vars and ints are assignment-compatible
// d = a[0,0];       // error: not assignment-compatible (different base object size)

   int [2,3] e = {{0,1,2}, {3,4,5}};
   int [2,3] f = foo();
   assert(e == f);

int[2,3] foo(void) {
   int[2,3] retval = {{0,1,2}, {3,4,5}};
   return retval;

Array accesses are checked at runtime to ensure that they are within the array bounds.