2010-12-17 16 views
13

¿Por qué no podemos usar el doble puntero para representar dos matrices dimensionales?¿Por qué no podemos usar el doble puntero para representar dos matrices dimensionales?

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

¿Por qué aquí no funciona el doble puntero (** ptr) en esta expansión?

+0

¿Qué código ha compilado que sea similar al código en su pregunta? –

+1

Huye de matrices multidimensionales (excepto quizás las pequeñas). –

+2

@Alexandre C. Las matrices multidimensionales son simples, útiles y eficientes. ¿Por qué querrías escaparte de ellos? – Shahbaz

Respuesta

8

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 sólo un puntero al elemento de inicio, y un número 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; 
} 
+1

Mi pregunta es por qué y cómo está funcionando. – Thangaraj

7

En C, una matriz de dos dimensiones es una matriz de matrices.

Se necesita un puntero a matriz para referirse a ella, no un doble puntero:

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

Para un puntero doble para referirse a "los datos de 2 dimensiones", se debe hacer referencia a la primera 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 sintaxis [][] utilizada para acceder a los datos: los datos en sí están estructurados de manera bastante diferente.

1

Comencemos hablando de código legal. Lo que has escrito (suponiendo que hay un carácter en frente de cada declaración) no compilará, 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 los caracteres individuales en lo anterior, es necesario especificar el elemento del que provienen:

char* pc = *arr; 

quiere trabajar, si desea acceder a los caracteres desde el primer elemento en arr.

C++ no tiene dos matrices dimensionales. 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.

3

Hacer un conjunto de punteros a cada fila con el fin de obtener un objeto que "se parece" a una matriz multidimensional de tamaño variable es una opción de diseño costoso en aras 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 usted quiere que "se vea bonito" para que pueda escribir m[y][x], usted debe utilizar un lenguaje diferente, tal vez C++.

+3

puede usar matrices de longitud variable para que el compilador realice el cómputo de compensación para usted: 'int (* foo) [cols] = malloc (sizeof * foo * rows)' hace posible el uso del conocido 'foo [i] [j] 'sintaxis; – Christoph

+0

@Christoph: De hecho, si tiene un compilador C99, esto funciona. Sin embargo, debe organizar pasar las dimensiones de manera adecuada a todas las llamadas a funciones a las que le pase la matriz. –

33

voy a tratar de dibujar la forma

int array[10][6]; 

y

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

mirada al igual que en la memoria y en qué son diferentes (y que no se pueden lanzar el uno al otro)

array parece:

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

array2 parece:

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

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

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

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

Una matriz dinámica de 2d, sin embargo, 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 apuntando a una sola variable, o apuntando a otra matriz. Y cada uno de esos punteros se configuran individualmente, por lo que pueden tener diferentes naturalezas.

Si tiene que pasar el puntero del array algún lugar, no se puede echarlo a int ** (imaginar lo que sucedería Los int valores de las celdas de array se interpretan como punteros y dereferenced -.> Bam Fallo de segmentación!) Sin embargo, puede pensar en array como una matriz de 1d de int [6] s; es una matriz de elementos 1d, con el tipo int [6]. Para escribirlo, diga

int (*p)[6] = array; 
Cuestiones relacionadas