When you write an array as a function, the compiler will silently "adjust" that array and replace it with a pointer to the first element. So when you write void func (int x[3])
the compiler silently replaces this with void func (int* x)
where the pointer points at the first item of the array.
The reason why C was designed this way is not avoid having large arrays getting pushed on the stack, which would be slow and memory-consuming.
In your case, the function void printField(int field[3][3])
gets silently adjusted behind the lines to
void printField(int (*field)[3])
which is an array pointer pointing at the first element, which is a int[3]
array. Which can still be used as field[i][j]
, so all is well. You can pretend that it is an array inside the function.
void printField(int field)
obviously doesn't make any sense. This is not an array but a single item. You can't use []
on a plain int and that's what the compiler is telling you: "subscripted value is neither array nor pointer nor vector".
void printField(int field[][]){...}
doesn't work either, because an empty []
means "declare an array of incomplete type". It can't be used before the array size is defined.
In case of void printField(int field[])
this happens to work because of the above mentioned "array adjustment" rule of functions. The compiler doesn't have to know the array size, because it just replaces the array with int*
anyway.
But in the case with two unknown dimensions, the compiler tries to adjust int field[][]
to int (*field)[]
. This is a pointer to an array of incomplete type and can't be used by the function.
You could however do int field[][3]
and it will work just fine.