Q:

passing multi-dimentional array as function argument

Suppose i have two dimentional array like this: 
A[2][3] = {{1,2,4},{2,5,15}}
and if i were to pass it as a function argument 
#include <stdio.h>

int fun(int A[][3])  // or int fun( int (*A)[3])
{
.
.
}

main()
{
int A[2][3] = {{1,2,4},{2,5,15}}; 
fun(A); 
}

Q) Why is this first block can be empty in function argument like this [] and it can stay empty why can't others stay empty as well like A[][] ? Or why this is wrong **A as a function argument?
Now if i have a three dimentional array like this: 
A[2][3][4] = {{{2,21,12,34,23},{322,34,34,23},{323,32,112,324}}, {{23,231,21,233},{23,5,65,2},{3,23,234,34}}}
and if i were to pass it as a function argument 
#include <stdio.h>

int fun(int A[][3][4])  // or int fun( int (*A)[3][4])
{
.
.
}

main()
{
int A[2][3][4] = {{{2,21,12,34,23},{322,34,34,23},{323,32,112,324}}, {{23,231,21,233},{23,5,65,2},{3,23,234,34}}}

fun(A); 
}

Q) Why is this first block can be empty in function argument like this [] and it can stay empty why can't others stay empty as well like A[][][] ? Or why this is wrong ***A as a function argument?

A:

The Standard says:

An lvalue or rvalue of type “array of N T” or “array of unknown bound
  of T” can be converted to an rvalue of type “pointer to T.” The result
  is a pointer to the first element of the array.

Simply put, it allows argument int A[x][y][z] to be converted to int (A*)[y][z]. We usually say that such an array decays to a pointer.
The Standard also says:

Parameter declarations that differ only in a pointer * versus an array
  [] are equivalent. That is, the array declaration is adjusted to
  become a pointer declaration (8.3.5). Only the second and subsequent
  array dimensions are significant in parameter types (8.3.4).

Which means that int (A*)[y][z] is no difference from int A[][y][z] when used as function parameter.
Thus, it's ok to just pass int A[x][y][z] (but not int A[][][z] or int A[][][], etc) to a function which requires a parameter of type int A[][y][z].
Why size of low dimensions are required? Because compilers need to know the type of element A* points to (here is int [y][z]) so that it can correctly do pointer arithmetic. E.g., A's value = A's value + sizeof(int) * y * z when you ++A.

