Code:
#include <stdio.h>
#include <stdlib.h>
int ***makeArray ( int x, int y, int z )
{
int ***pa = malloc( x * sizeof *pa );
int **pb = malloc( x * y * sizeof *pb );
int *pc = calloc( x * y * z, sizeof *pc );
int r, c;
for ( r = 0 ; r < x ; r++, pb += y ) {
pa[r] = pb;
for ( c = 0 ; c < y ; c++, pc += z ) {
pa[r][c] = pc;
}
}
return pa;
}
void freeArray ( int ***array )
{
free( array[0][0] );
free( array[0] );
free( array );
}
// With the sizes of y and z being 16 and 64 respectively, on
// a machine with 4-byte integers, the number of bytes occupied
// by each z is 0x100 bytes, and the number of bytes for each
// plane of y*z is 0x1000 bytes.
// For an address of 0xnnnnYXnn, then X increments in each row
// and Y increments in each column.
// This basically shows the whole array is one contiguous block of memory
void showAddresses ( int ***a, int x, int y, int z )
{
int r, c;
for ( r = 0 ; r < 10 && r < x ; r++ ) {
printf( "Addresses on %d: ", r );
for ( c = 0 ; c < 5 && c < y ; c++ ) {
printf( "%p ", (void*)&a[r][c][0] );
}
printf( "\n" );
}
}
void useArray ( int ***a, int x, int y, int z )
{
// set some values
a[5][5][5] = 1;
a[5][4][5] = 2; // directly left/right
a[6][5][5] = 3; // directly above/below
a[2][7][9] = 279; // something further away
int *c = &a[5][5][5]; // our centre element
printf( "Centre=%d\n", c[0] );
// The three () expressions show the pitch to get from the current
// position to the neighbouring position in each dimension
printf( "Left/Right=%d\n", c[(0) + (-1*z) + (0)] ); // [0][-1][0] from [5][5][5]
printf( "Above/Below=%d\n", c[(1*y*z) + (0) + (0)] ); // [1][0][0]
printf( "Far away=%d\n", c[(-3*y*z) + (2*z) + (4)] ); // [-3][2][4]
}
int main(void)
{
int xs = 10, ys = 16, zs = 64;
int ***a = makeArray( xs, ys, zs );
showAddresses( a, xs, ys, zs );
useArray( a, xs, ys, zs );
freeArray( a );
return 0;
}