multidimensionales - punteros c++
¿Por qué no podemos usar el puntero doble para representar matrices bidimensionales? (5)
En C, una matriz bidimensional es una matriz de matrices .
Necesita un puntero a matriz para referirse a él, no un puntero doble:
char array[2][6] = {"hello", "hai"};
char (*p)[6] = array;
//char **x = array; // doesn''t compile.
Para que un puntero doble se refiera a "datos bidimensionales", debe referirse 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 bidimensional, entonces no existe una matriz correspondiente de punteros.
La única similitud entre los dos es la sintaxis [][]
utilizada para acceder a los datos: los datos en sí están estructurados de manera muy diferente.
¿Por qué no podemos usar el puntero doble para representar matrices bidimensionales?
arr[2][5] = {"hello","hai"};
**ptr = arr;
Aquí, ¿por qué el puntero doble (** ptr) no funciona en este ejemplo?
Hacer una matriz de punteros a cada fila para obtener un objeto que "se parece" a una matriz multidimensional de tamaño variable es una opción de diseño costosa por el bien del azúcar sintáctica . No lo hagas
La forma correcta de hacer una matriz multidimensional de tamaño variable es algo 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 quiere que se vea "bonito" para poder escribir m[y][x]
, debería usar un lenguaje diferente, tal vez C ++.
Tener puntero a puntero significa que cada fila (o columna, si prefiere 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 de inicio y un entero que especifica el número 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;
}
Vamos a empezar hablando del código legal. Lo que ha escrito (asumiendo un carácter delante de cada declaración) no se compilará, por varias razones: tiene demasiados inicializadores (seis caracteres para arr [0], y su tamaño es 5), y por supuesto, carácter ** p no tiene un tipo compatible con char arr [2] [5]. Corrigiendo por esos problemas, obtenemos:
char arr[2][6] = { "hello", "hai" };
char (*p)[6] = arr;
Sin ningún doble puntero. Si desea acceder a los caracteres individuales de lo anterior, debe especificar el elemento del que provienen:
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 matriz [6] de char. La conversión implícita de matriz a puntero da como resultado puntero a matriz [6] de char. Después de eso, por supuesto, no hay una conversión de matriz a puntero, porque ya no tiene una matriz.
Voy a tratar de dibujar como
int array[10][6];
y
int **array2 = malloc(10 * sizeof *array2);
for (int i = 0; i < 10; ++i)
array2[i] = malloc(6 * sizeof **array2);
se ven como en la memoria y en qué se diferencian (y que no se pueden unir entre sí)
array
ve como
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | | | ..............| | | (10*6 elements of type int)
- - - - - - - - - - - - - - - - - - - - - -
< first row >< second row> ...
array2
ve como:
_ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | (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)
cuenta que para array
, esta fórmula también funciona (lee hasta el final de la publicación, y luego los comentarios )).
Es decir, una matriz 2d estática es de hecho una matriz 1d con filas puestas en una línea. El índice se calcula por la row * number_of_columns_in_one_row + column
la fórmula row * number_of_columns_in_one_row + column
.
Una matriz 2D dinámica, sin embargo, es solo una matriz 1D de punteros. Cada puntero se asigna dinámicamente para apuntar a otra matriz 1d. En verdad, ese puntero podría ser cualquier cosa. Podría ser NULL
, o apuntar a una sola variable, o apuntar a otra matriz. Y cada uno de esos punteros se establece individualmente, por lo que pueden tener diferentes naturalezas.
Si necesita pasar el puntero de la array
algún lugar, no puede convertirlo en int **
(imagine lo que sucedería. Los valores int
de las celdas de la array
se interpretan como punteros y se eliminan de la referencia -> ¡Bam! ¡Fallo de segmentación!). Sin embargo, puede pensar en la array
como una matriz 1d de int [6]
s; es una matriz de elementos 1d, con el tipo int [6]
. Para escribir eso, dices
int (*p)[6] = array;