What you want can't work directly. For indexing a multi-dimensional array, all but the very first dimension need to be part of the type and here's why:
The indexing operator operates on pointers by first adding an index to the pointer and then dereferencing it. The identifier of an array evaluates to a pointer to its first element (except when e.g. used with sizeof, _Alignof and &), so indexing on arrays works as you would expect.
It's very simple in the case of a single-dimension array. With 
int a[42];
a evaluates to a pointer of type int *  and indexing works the following way: a[18] => *(a + 18).
Now in a 2-dimensional array, all the elements are stored contiguously ("row" after "row" if you want to understand it as a matrix), and what's making the indexing "magic" work is the types involved. Take for example:
int a[16][42];
Here, the elements of a have the type int ()[42] (42-element array of int). According to the rules above, evaluating an expression of this type in most contexts again yields an int * pointer. But what about a itself? Well, it's an array of int ()[42] so a will evaluate to a pointer to 42-element array of int: int (*)[42]. Then let's have a look at what the indexing operator does:
a[3][18] => *(*(a + 3) + 18)
With a evaluating to the address of a with type int (*)[42], this inner addition of 3 can properly add 42 * sizeof(int). This would be impossible if the second dimension wasn't known in the type.
I guess it's simple to deduce the example for the n-dimensional case.
In your case, you have two possibilities to achieve something similar to what you want.
- Use a dynamically allocated flat array with size - 6*N*N. You can calculate the indices yourself if you save- Nsomewhere.
 
- Somewhat less efficient, but yielding better readable code, you could use an array of pointers to arrays of pointers to int (multiple indirection). You could e.g. do - int ***a = malloc(6 * sizeof *int);
for (size_t i = 0; i < 6; ++i)
{
    a[i] = malloc(N * sizeof *(a[i]));
    for (size_t j = 0; j < N ++j)
    {
        a[i][j] = malloc(N* sizeof *(a[i][j]));
    }
}
// add error checking to malloc calls!
 - Then your accesses will look just like those to a normal 3d array, but it's stored internally as many arrays with pointers to the other arrays instead of in a big contiguous block. - I don't think it's worth using this many indirections, just to avoid writing e.g. - a[2*N*N+5*N+4]to access the element at- 2,5,4, so my recommendation would be the first method.