Why aren't these function prototypes equivalent?
void print_matrix(char *name, int SX, int SY, int m[SX][SY])
void print_matrix(char *name, int SX, int SY, int **m)
Why aren't these function prototypes equivalent?
void print_matrix(char *name, int SX, int SY, int m[SX][SY])
void print_matrix(char *name, int SX, int SY, int **m)
 
    
     
    
    Even though the two function arguments can be consumed in the same way, namely via m[i][j], they're quite different:
int m[M][N] is an array of M arrays of N ints.
int **m is a pointer to a pointer to an int.
You cannot pass arrays as function arguments, so an "array of K elements of type T" decays to a "pointer-to-T", pointing to the first element of the array. Thus it is permissible and equivalent to write the first form as int m[][N] in a function argument, since the value M is lost. However, the value N is not lost; it is part of the type!
So the following are admissible/erroneous for the first form:
void f(int arr[M][N]);
int a[M][N];
int b[2*M][N];
int c[M][N + 1];
f(a);   // OK
f(b);   // OK; slowest extent is forgotten in the decay
//f(c); // Error! 'c' is not an array of {array of N ints}.
For the second form, the meaning is rather different:
void g(int **p);
int a;
int * pa = &a;
g(&pa);          // fine, pointer to 'pa'
int arr[M][N];
// g(arr);  // Error, makes no sense
The expression arr designates the pointer to the first element of an array of arrays of N integers, i.e. its type is int (*)[N]. Dereferencing it gives an array of N integers, and not a pointer to an integer.
There is no way to convert the expression arr into a pointer to a pointer: If you said,
int ** fool = (int**)arr;
then *fool would point to the first element of the first array (arr[0]), and not to an int pointer. So you cannot dereference the value further, because the value is not a pointer.
The only correct way to pass a two-dimensional array as a double pointer is to construct an intermediate helper array:
int * helper[M];   // array of pointers
for (size_t i = 0; i != M; ++i)
{
    helper[i] = arr[i]; // implicit decay
}
g(helper);  // or "g(&helper[0])"
