¿Cuál es la diferencia entre array y ** array

¿Por qué estos prototipos de funciones no son equivalentes?

void print_matrix(char *name, int SX, int SY, int m[SX][SY]) void print_matrix(char *name, int SX, int SY, int **m) 

Aunque los dos argumentos de función se pueden consumir de la misma manera, es decir, a través de m[i][j] , son bastante diferentes:

  • int m[M][N] es una matriz de matrices M de N ints.

  • int **m es un puntero a un puntero a un int.

No puede pasar matrices como argumentos de función, por lo que una “matriz de K elementos del tipo T ” decae en un “puntero a T “, apuntando al primer elemento de la matriz. Por lo tanto, es permisible y equivalente escribir la primera forma como int m[][N] en un argumento de función, ya que el valor M se pierde. Sin embargo, el valor N no se pierde; ¡Es parte del tipo!

Así que lo siguiente es admisible / erróneo para la primera forma:

 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}. 

Para la segunda forma, el significado es bastante diferente:

 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 

La expresión arr designa el puntero al primer elemento de una matriz de matrices de N enteros, es decir, su tipo es int (*)[N] . Al anular la referencia, se obtiene una matriz de N enteros y no un puntero a un entero.

No hay forma de convertir la expresión arr en un puntero a un puntero: si dijiste,

 int ** fool = (int**)arr; 

entonces *fool apuntaría al primer elemento de la primera matriz ( arr[0] ), y no a un puntero int . Por lo tanto, no puede desreferenciar más el valor, porque el valor no es un puntero .

La única forma correcta de pasar una matriz bidimensional como un puntero doble es construir una matriz auxiliar intermedia:

 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])"