¿Por qué no podemos usar doble puntero para representar matrices bidimensionales?

¿Por qué no podemos usar doble puntero para representar matrices bidimensionales?

arr[2][5] = {"hello","hai"}; **ptr = arr; 

Aquí, ¿por qué el puntero doble (** ptr) no funciona en esta expansión?

Voy a tratar de dibujar cómo

 int array[10][6]; 

y

 int **array2 = malloc(10 * sizeof *array2); for (int i = 0; i < 10; ++i) array2[i] = malloc(6 * sizeof **array2); 

parecer en la memoria y en cómo son diferentes (y que no se pueden lanzar el uno al otro)

array ve así:

  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | | | | | | | | | | | ..............| | | (10*6 elements of type int) - - - - - - - - - - - - - - - - - - - - - - < first row >< second row> ... 

array2 ve así:

  _ _ _ _ _ _ _ _ _ _ | | | | | | | | | | | (10 elements of type int *) - - - - - - - - - - | | .... | _ _ _ _ _ _ | | \-->| | | | | | | (6 elements of type int) | | - - - - - - | | | | _ _ _ _ _ _ | \ -->| | | | | | | (6 elements of type int) | - - - - - - | | | _ _ _ _ _ _ \ -->| | | | | | | (6 elements of type int) - - - - - - 

Cuando dices array[x][y] , se traduce en *(((int *)array)+x*6+y)

Mientras, cuando dices array2[x][y] , se traduce en *(*(array2+x)+y)

Es decir, una matriz 2d estática es de hecho una matriz de 1d con filas en una línea. El índice se calcula mediante la fórmula row * number_of_columns_in_one_row + column .

Sin embargo, una matriz dinámica de 2d es solo una matriz de punteros de 1d. Cada puntero se asigna dinámicamente para apuntar a otra matriz de 1d. En verdad, ese puntero podría ser cualquier cosa. Podría ser NULL , o señalar una sola variable, o apuntar a otra matriz. Y cada uno de esos punteros se configuran individualmente, por lo que pueden tener diferentes naturalezas.

Si necesita pasar el puntero de la array algún lugar, no puede convertirlo a int ** (imagínese lo que sucedería. Los valores int de las celdas de la array se interpretan como punteros y se eliminan las referencias -> ¡Error de segmentación de Bam!). Sin embargo, puede pensar en array como una matriz 1d de int [6] s; eso es una matriz 1d de elementos, con tipo int [6] . Para escribir eso, dices

 int (*p)[6] = array; 

Tener puntero a puntero significa que cada fila (o columna, si prefieres pensar de esa manera) puede tener una longitud diferente de las otras filas / columnas.

También puede representar una matriz 2D con solo un puntero al elemento inicial y un número entero que especifica la cantidad de elementos por fila / columna:

 void matrix_set(double *first, size_t row_size, size_t x, size_t y, double value) { first[y * row_size + x] = value; } 

En C, una matriz bidimensional es una matriz de matrices .

Necesita un puntero a matriz para referirse a él, no un doble puntero:

 char array[2][6] = {"hello", "hai"}; char (*p)[6] = array; //char **x = array; // doesn't compile. 

Para que un doble puntero haga referencia a “datos bidimensionales”, debe hacer referencia al primer elemento de una matriz de punteros . Pero una matriz bidimensional en C (matriz de matrices) no es lo mismo que una matriz de punteros, y si solo define una matriz 2-D, entonces no existe una matriz correspondiente de punteros.

La única similitud entre los dos es la syntax [][] utilizada para acceder a los datos: los datos en sí están estructurados de manera bastante diferente.

Hacer una serie de punteros a cada fila para obtener un objeto que “se parece” a una matriz multidimensional de tamaño variable es una opción costosa de diseño por el bien del azúcar sintáctico . No lo hagas

La forma correcta de hacer una matriz multidimensional de tamaño variable es algo así como:

 if (w > SIZE_MAX/sizeof *m/h) goto error; m = malloc(w * h * sizeof *m); if (!m) goto error; ... m[y*w+x] = foo; 

Si desea que se vea “bonito” para que pueda escribir m[y][x] , debe usar un idioma diferente, quizás C ++.

Comencemos hablando de código legal. Lo que has escrito (suponiendo que hay un carácter en frente de cada statement) no comstackrá, por varias razones: tienes demasiados inicializadores (seis caracteres para arr [0], y su tamaño es 5) y, por supuesto, char ** p no tiene un tipo compatible con char arr [2] [5]. Corrigiendo esos problemas, obtenemos:

 char arr[2][6] = { "hello", "hai" }; char (*p)[6] = arr; 

Sin ningún doble puntero Si desea acceder a caracteres individuales en el cuadro anterior, debe especificar el elemento del que proceden:

 char* pc = *arr; 

funcionaría si quisiera acceder a los caracteres del primer elemento en arr.

C ++ no tiene matrices bidimensionales. La primera definición anterior define una matriz [2] o una matriz [6] de char. La matriz implícita a la conversión del puntero da como resultado un puntero a la matriz [6] de char. Después de eso, por supuesto, no hay una matriz para la conversión de puntero, porque ya no tiene una matriz.