¿Por qué es x [0]! = X [0] [0]! = X [0] [0] [0]?

149

Estoy estudiando un poco de C ++ y estoy luchando con punteros. Entiendo que puedo tener 3 niveles de punteros declarando:

int *(*x)[5];

por lo que *xes un puntero a una matriz de 5 elementos que son punteros a int. También lo sé x[0] = *(x+0);, x[1] = *(x+1)y así sucesivamente ...

Entonces, dada la declaración anterior, ¿por qué x[0] != x[0][0] != x[0][0][0]?

Leo91
fuente
58
x[0], x[0][0]y x[0][0][0]tienen diferentes tipos. No se pueden comparar. ¿Qué quieres decir con !=?
bolov
44
@celticminstrel no son lo mismo: int **x[5]es una matriz de 5 elementos. Un elemento es un puntero a puntero a int`
bolov 05 de
55
@celticminstrel int** x[5]sería una matriz de cinco punteros que apuntan a punteros que apuntan a int. int *(*x)[5]es un puntero a una matriz de cinco punteros que apuntan a int.
emlai
55
@celticminstrel regla derecha-izquierda , regla spirale , galimatías C ↔ Inglés y tu 'en camino a convertirte en un programador de tres estrellas :)
bolov
55
@ Leo91: Primero, tienes dos niveles de punteros aquí, no tres. En segundo lugar, ¿qué x[0] != x[0][0] != x[0][0][0]significa? Esta no es una comparación válida en C ++. Incluso si lo divide en x[0] != x[0][0]y x[0][0] != x[0][0][0]todavía no es válido. Entonces, ¿qué significa tu pregunta?
AnT

Respuestas:

261

xes un puntero a una matriz de 5 punteros a int.
x[0]es una matriz de 5 punteros a int.
x[0][0]es un puntero a un int.
x[0][0][0]es un int.

                       x[0]
   Pointer to array  +------+                                 x[0][0][0]         
x -----------------> |      |         Pointer to int           +-------+
               0x500 | 0x100| x[0][0]---------------->   0x100 |  10   |
x is a pointer to    |      |                                  +-------+
an array of 5        +------+                        
pointers to int      |      |         Pointer to int                             
               0x504 | 0x222| x[0][1]---------------->   0x222                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x508 | 0x001| x[0][2]---------------->   0x001                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x50C | 0x123| x[0][3]---------------->   0x123                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x510 | 0x000| x[0][4]---------------->   0x000                    
                     |      |                                             
                     +------+                                             

Puedes ver eso

  • x[0]es una matriz y se convertirá en puntero a su primer elemento cuando se use en una expresión (con algunas excepciones). Por lo tantox[0] lo dará la dirección de su primer elemento x[0][0]que es 0x500.
  • x[0][0] contiene la dirección de un int que es 0x100.
  • x[0][0][0] contiene un int valor de 10.

Entonces, x[0]es igual a &x[0][0]y por lo tanto &x[0][0] != x[0][0],.
Por lo tanto, x[0] != x[0][0] != x[0][0][0].

hacks
fuente
Este diagrama es un poco confuso para mí: 0x100debería aparecer inmediatamente a la izquierda del cuadro que contiene 10, de la misma manera que 0x500aparece a la izquierda de su cuadro. En lugar de estar muy a la izquierda y abajo.
MM
@MattMcNabb; No creo que deba ser confuso, pero cambia según su sugerencia para mayor claridad.
piratea el
44
@haccks - Es un placer :) La razón por la que ese diagrama es excelente es porque ni siquiera necesita la explicación que dio a continuación. Ese diagrama en sí mismo se explica por sí mismo porque ya responde a la pregunta. El texto que sigue es simplemente una bonificación.
rayryeng
1
También puede usar yed, un software de diagramación. Me ayuda mucho a organizar mis pensamientos
rpax
@GrijeshChauhan Utilizo asciiflow para los comentarios del código, yeD para las presentaciones :)
rpax
133
x[0] != x[0][0] != x[0][0][0]

es, según tu propia publicación,

*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)`  

que se simplifica

*x != **x != ***x

¿Por qué debería ser igual?
El primero es la dirección de algún puntero.
El segundo es la dirección de otro puntero.
Y el tercero tiene algún intvalor.

deviantfan
fuente
No puedo entender ... si x [0], x [0] [0], x [0] [0] [0] es equivalente a * (x + 0), * (x + 0 + 0) , * (x + 0 + 0 + 0), ¿por qué deberían tener direcciones diferentes?
Leo91
41
@ Leo91 x[0][0]es (x[0])[0], es decir *((*(x+0))+0), no *(x+0+0). La desreferencia ocurre antes del segundo [0].
emlai
44
@ Leo91 x[0][0] != *(x+0+0)al igual que x[2][3] != x[3][2].
Jueves
@ Leo91 Se eliminó el segundo comentario de que "lo tienes ahora". ¿No entiendes algo (que podría explicarse mejor en la respuesta), o no es esto lo que haces? (a algunas personas les gusta eliminar comentarios sin mucho contenido informativo)
deviantfan
@deviantfan lo siento, no puedo entender lo que quieres decir. Entiendo las respuestas y muchos comentarios que me ayudaron a aclarar el concepto.
Leo91
50

Aquí está el diseño de memoria de su puntero:

   +------------------+
x: | address of array |
   +------------------+
            |
            V
            +-----------+-----------+-----------+-----------+-----------+
            | pointer 0 | pointer 1 | pointer 2 | pointer 3 | pointer 4 |
            +-----------+-----------+-----------+-----------+-----------+
                  |
                  V
                  +--------------+
                  | some integer |
                  +--------------+

x[0]produce "dirección de matriz",
x[0][0]produce "puntero 0",
x[0][0][0]produce "algún número entero".

Creo que debería ser obvio ahora, por qué todos son diferentes.


Lo anterior es lo suficientemente cercano para la comprensión básica, por eso lo escribí de la manera en que lo escribí. Sin embargo, como los hacks señalan correctamente, la primera línea no es 100% precisa. Así que aquí vienen todos los detalles finos:

A partir de la definición del lenguaje C, el valor de x[0]es la matriz completa de punteros enteros. Sin embargo, las matrices son algo con lo que realmente no puedes hacer nada en C. Siempre manipulas su dirección o sus elementos, nunca la matriz completa en su conjunto:

  1. Puedes pasar x[0]al sizeofoperador. Pero eso no es realmente un uso del valor, su resultado depende solo del tipo.

  2. Puede tomar su dirección que produce el valor de x, es decir, "dirección de matriz" con el tipo int*(*)[5]. En otras palabras:&x[0] <=> &*(x + 0) <=> (x + 0) <=> x

  3. En todos los demás contextos , el valor de x[0]decaerá en un puntero al primer elemento de la matriz. Es decir, un puntero con el valor "dirección de matriz" y el tipo int**. El efecto es el mismo que si hubiera lanzado xun puntero de tipo int**.

Debido a la caída de la matriz de punteros en el caso 3., todos los usos de x[0]finalmente resultan en un puntero que señala el comienzo de la matriz de punteros; la llamada printf("%p", x[0])imprimirá el contenido de las celdas de memoria etiquetadas como "dirección de la matriz".

cmaster - restablecer monica
fuente
1
x[0]No es la dirección de la matriz.
piratea el
1
@haccks Sí, siguiendo la letra del estándar, x[0]no es la dirección de la matriz, es la matriz misma. He agregado una explicación en profundidad de esto y de por qué escribí que x[0]es la "dirección de la matriz". Espero que te guste.
cmaster - restablecer monica
¡Gráficos increíbles que lo explican perfectamente bien!
MK
"Sin embargo, las matrices son algo con lo que realmente no se puede hacer nada en C." -> Ejemplo de contador: printf("%zu\n", sizeof x[0]);informa el tamaño de la matriz, no el tamaño de un puntero.
chux - Restablece a Monica el
@ chux-ReinstateMonica Y seguí diciendo "Siempre manipulas su dirección o sus elementos, nunca toda la matriz en su conjunto", seguido del punto 1 de la enumeración donde hablo sobre el efecto de sizeof x[0]...
cmaster - reinstalar a monica el
18
  • x[0]elimina la referencia del puntero más externo ( puntero a la matriz de tamaño 5 del puntero a int) y da como resultado una matriz de tamaño 5 del puntero a int;
  • x[0][0]desreferencia el puntero más externo e indexa la matriz, lo que resulta en un puntero a int;
  • x[0][0][0] desreferencia todo, lo que resulta en un valor concreto.

Por cierto, si alguna vez te sientes confundido por el significado de este tipo de declaraciones, usa cdecl .

d125q
fuente
11

Vamos a considerar paso a paso expresiones x[0], x[0][0]y x[0][0][0].

Como xse define de la siguiente manera

int *(*x)[5];

entonces expresión x[0]es una matriz de tipo int *[5]. Tenga en cuenta que expresión x[0]es equivalente a expresión *x. Eso es desreferenciar un puntero a una matriz, obtenemos la matriz en sí. Vamos a denotarlo como si es que tenemos una declaración

int * y[5];

La expresión x[0][0]es equivalente y[0]y tiene tipo int *. Vamos a denotarlo como z, es decir, tenemos una declaración

int *z;

expresión x[0][0][0]es equivalente a expresión y[0][0]que a su vez es equivalente a expresión z[0]y tiene tipo int.

Entonces tenemos

x[0] tiene tipo int *[5]

x[0][0] tiene tipo int *

x[0][0][0] tiene tipo int

Por lo tanto, son objetos de diferentes tipos y, por cierto, de diferentes tamaños.

Ejecutar por ejemplo

std::cout << sizeof( x[0] ) << std::endl;
std::cout << sizeof( x[0][0] ) << std::endl;
std::cout << sizeof( x[0][0][0] ) << std::endl;
Vlad de Moscú
fuente
10

Lo primero que tengo que decir es que

x [0] = * (x + 0) = * x;

x [0] [0] = * (* (x + 0) + 0) = * * x;

x [0] [0] [0] = * (* (* (x + 0) + 0)) = * * * x;

Entonces * x ≠ * * x ≠ * * * x

De la siguiente imagen todas las cosas están claras.

  x[0][0][0]= 2000

  x[0][0]   = 1001

  x[0]      = 10

ingrese la descripción de la imagen aquí

Es solo un ejemplo, donde el valor de x [0] [0] [0] = 10

y la dirección de x [0] [0] [0] es 1001

esa dirección se almacena en x [0] [0] = 1001

y la dirección de x [0] [0] es 2000

y esa dirección se almacena en x [0] = 2000

Entonces x [0] [0] [0] x [0] [0] x [0]

.

EDICIONES

Programa 1:

{
int ***x;
x=(int***)malloc(sizeof(int***));
*x=(int**)malloc(sizeof(int**));
**x=(int*)malloc(sizeof(int*));
***x=10;
printf("%d   %d   %d   %d\n",x,*x,**x,***x);
printf("%d   %d   %d   %d   %d",x[0][0][0],x[0][0],x[0],x,&x);
}

Salida

142041096 142041112 142041128 10
10 142041128 142041112 142041096 -1076392836

Programa 2:

{
int x[1][1][1]={10};
printf("%d   %d   %d   %d \n ",x[0][0][0],x[0][0],x[0],&x);
}

Salida

10   -1074058436   -1074058436   -1074058436 
apm
fuente
3
Tu respuesta es engañosa. x[0]No contiene la dirección de la hormiga. Es una gran variedad. Se descompondrá al puntero a su primer elemento.
piratea el
Ummm ... ¿qué significa? Su edición es como la guinda del pastel a su respuesta incorrecta. No tiene sentido
piratea el
@haccks Si solo usa punteros, esta respuesta será correcta. Habrá algunos cambios en la sección de dirección cuando se use Array
apm
7

Si tuviera que ver las matrices desde una perspectiva del mundo real, aparecería así:

x[0]Es un contenedor de carga lleno de cajas.
x[0][0]es una caja individual, llena de cajas de zapatos, dentro del contenedor de carga.
x[0][0][0]es una única caja de zapatos dentro de la caja, dentro del contenedor de carga.

Incluso si fuera la única caja de zapatos en la única caja en el contenedor de carga, sigue siendo una caja de zapatos y no un contenedor de carga

David Opcional Courtenay
fuente
1
¿No x[0][0]sería una sola caja llena de pedazos de papel que tienen las ubicaciones de las cajas de zapatos escritas en ellas?
wchargin
4

Hay un principio en C ++ para que: una declaración de una variable indique exactamente la forma de usar la variable. Considera tu declaración:

int *(*x)[5];

que puede reescribirse como (para más claro):

int *((*x)[5]);

Debido al principio, tenemos:

*((*x)[i]) is treated as an int value (i = 0..4)
 (*x)[i] is treated as an int* pointer (i = 0..4)
 *x is treated as an int** pointer
 x is treated as an int*** pointer

Por lo tanto:

x[0] is an int** pointer
 x[0][0] = (x[0]) [0] is an int* pointer
 x[0][0][0] = (x[0][0]) [0] is an int value

Para que puedas descubrir la diferencia.

Nghia Bui
fuente
1
x[0]es una matriz de 5 pulgadas, no un puntero. (puede decaer a un puntero en la mayoría de los contextos, pero la distinción es importante aquí).
MM
De acuerdo, pero deberías decir: x [0] es una matriz de 5 punteros int *
Nghia Bui
Para dar la derivación correcta por @MattMcNabb: *(*x)[5]es un int, así (*x)[5]es un int *, entonces*x is an (int *)[5], so xis an *((int *)[5]). Es decir, xes un puntero a un conjunto de 5 punteros a int.
wchargin
2

Estás intentando comparar diferentes tipos por valor

Si toma las direcciones, puede obtener más de lo que espera

Tenga en cuenta que su declaración hace la diferencia

 int y [5][5][5];

permitiría a las comparaciones que desea, ya que y, y[0], y[0][0], y[0][0][0]tendría diferentes valores y tipos, pero la misma dirección

int **x[5];

No ocupa espacio contiguo.

xy x [0]tener la misma dirección, pero x[0][0]y x[0][0][0]son cada uno en diferentes direcciones

Glenn Teitelbaum
fuente
2
int *(*x)[5]es diferente aint **x[5]
MM
2

Ser pun puntero: está apilando las desreferencias con p[0][0], lo que es equivalente a*((*(p+0))+0) .

En la referencia C (&) y la notación de desreferencia (*):

p == &p[0] == &(&p[0])[0] == &(&(&p[0])[0])[0])

Es equivalente a:

p == &*(p+0) == &*(&*(p+0))+0 == &*(&*(&*(p+0))+0)+0

Mira eso, el & * puede ser refactorizado, simplemente eliminándolo:

p == p+0 == p+0+0 == p+0+0+0 == (((((p+0)+0)+0)+0)+0)
Luciano
fuente
¿Qué intentas mostrar con todo después de tu primera oración? Solo tienes muchas variaciones p == p . &(&p[0])[0]es diferente ap[0][0]
MM
El chico preguntó por qué 'x [0]! = X [0] [0]! = X [0] [0] [0]' cuando x es un puntero, ¿verdad? Traté de mostrarle que puede quedar atrapado por la notación C de desreferencia (*) cuando apila [0]. Entonces, es un intento de mostrarle la notación correcta para que x sea igual x [0], haciendo referencia a x [0] nuevamente con &, y así sucesivamente.
Luciano
1

Las otras respuestas son correctas, pero ninguna de ellas enfatiza la idea de que es posible que las tres contengan el mismo valor , por lo que están de alguna manera incompletas.

La razón por la que esto no se puede entender a partir de las otras respuestas es que todas las ilustraciones, si bien son útiles y definitivamente razonables en la mayoría de las circunstancias, no cubren la situación en la que el puntero se xseñala a sí mismo.

Esto es bastante fácil de construir, pero claramente un poco más difícil de entender. En el siguiente programa, veremos cómo podemos forzar que los tres valores sean idénticos.

NOTA: El comportamiento en este programa no está definido, pero lo estoy publicando aquí simplemente como una demostración interesante de algo que los punteros pueden hacer, pero no deberían .

#include <stdio.h>

int main () {
  int *(*x)[5];

  x = (int *(*)[5]) &x;

  printf("%p\n", x[0]);
  printf("%p\n", x[0][0]);
  printf("%p\n", x[0][0][0]);
}

Esto se compila sin advertencias tanto en C89 como en C99, y el resultado es el siguiente:

$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c

Curiosamente, los tres valores son idénticos. ¡Pero esto no debería ser una sorpresa! Primero, analicemos el programa.

Declaramos xcomo un puntero a una matriz de 5 elementos donde cada elemento es de tipo puntero a int. Esta declaración asigna 4 bytes en la pila de tiempo de ejecución (o más, dependiendo de su implementación; en mi máquina, los punteros son 4 bytes), por lo que xse refiere a una ubicación de memoria real. En la familia de lenguajes C, los contenidos xson solo basura, algo que queda del uso anterior de la ubicación, por xlo que no apunta a ninguna parte, ciertamente no al espacio asignado.

Entonces, naturalmente, podemos tomar la dirección de la variable xy ponerla en algún lugar, así que eso es exactamente lo que hacemos. Pero seguiremos adelante y lo pondremos en x. Dado que &xtiene un tipo diferente dex , necesitamos hacer un reparto para que no recibamos advertencias.

El modelo de memoria se vería así:

0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+

Por lo tanto, el bloque de memoria de 4 bytes en la dirección 0xbfd9198ccontiene el patrón de bits correspondiente al valor hexadecimal 0xbfd9198c. Suficientemente simple.

A continuación, imprimimos los tres valores. Las otras respuestas explican a qué se refiere cada expresión, por lo que la relación debería ser clara ahora.

Podemos ver que los valores son los mismos, pero solo en un sentido de nivel muy bajo ... sus patrones de bits son idénticos, pero los datos de tipo asociados con cada expresión significan que sus valores interpretados son diferentes. Por ejemplo, si imprimimos x[0][0][0]usando la cadena de formato%d , obtendríamos un número negativo enorme, por lo que los "valores" son, en la práctica, diferentes, pero el patrón de bits es el mismo.

Esto es realmente simple ... en los diagramas, las flechas solo apuntan a la misma dirección de memoria en lugar de a diferentes direcciones. Sin embargo, aunque pudimos forzar un resultado esperado de un comportamiento indefinido, es solo eso: indefinido. Este no es un código de producción, sino simplemente una demostración en aras de la integridad.

En una situación razonable, usará mallocpara crear la matriz de 5 punteros int, y nuevamente para crear las entradas que se apuntan en esa matriz.mallocsiempre devuelve una dirección única (a menos que no tenga memoria, en cuyo caso devuelve NULL o 0), por lo que nunca tendrá que preocuparse por punteros autorreferenciales como este.

Esperemos que esa sea la respuesta completa que estás buscando. No debe esperar x[0], x[0][0]y x[0][0][0]ser igual, pero podrían serlo si se lo obliga. Si algo te pasó por la cabeza, ¡avísame para que te lo aclare!

Purag
fuente
Yo diría que otro uso extraño de punteros que he visto nunca.
piratea el
@haccks Sí, es bastante extraño, pero cuando lo desglosas, es tan básico como los otros ejemplos. Simplemente sucede que los patrones de bits son todos iguales.
Purag
Su código provoca un comportamiento indefinido. x[0]en realidad no representa un objeto válido del tipo correcto
MM
@MattMcNabb no está definido, y en realidad lo tengo muy claro. No estoy de acuerdo con el tipo. xes un puntero a una matriz, por lo que podemos usar el []operador para especificar un desplazamiento desde ese puntero y desreferenciarlo. ¿Qué hay de extraño allí? El resultado de x[0]es una matriz, y C no se queja si imprime eso usando, %pya que así es como se implementa debajo de todos modos.
Purag
Y compilar esto con la -pedanticbandera no produce advertencias, por lo que C está bien con los tipos ...
Purag
0

El tipo de int *(*x)[5]es, es int* (*)[5]decir, un puntero a una matriz de 5 punteros a ints.

  • xes la dirección de la primera matriz de 5 punteros a ints (una dirección con tipo int* (*)[5])
  • x[0]la dirección de la primera matriz de 5 punteros a ints (misma dirección con tipo int* [5]) (dirección de desplazamiento x por 0*sizeof(int* [5])ej. índice * tamaño-de-tipo-señalado-y desreferenciación)
  • x[0][0]es el primer puntero a un int en la matriz (la misma dirección con tipo int*) (dirección de desplazamiento x por 0*sizeof(int* [5])y desreferencia y luego por 0*sizeof(int*)y desreferencia)
  • x[0][0][0]es el primer int señalado por el puntero a un int (desplazamiento de la dirección x por 0*sizeof(int* [5])y desreferencia y desplazamiento de esa dirección por 0*sizeof(int*)y desreferenciación y desplazamiento de esa dirección por 0*sizeof(int)y desreferenciación)

El tipo de int *(*y)[5][5][5]es, es int* (*)[5][5][5]decir, un puntero a una matriz 3D de punteros de 5x5x5 a ints

  • x es la dirección de la primera matriz 3D de punteros de 5x5x5 a entradas con tipo int*(*)[5][5][5]
  • x[0]es la dirección de la primera matriz 3D de punteros de 5x5x5 a ints (dirección de desplazamiento x por 0*sizeof(int* [5][5][5])y desreferencia)
  • x[0][0]es la dirección de la primera matriz 2d de punteros 5x5 a ints (compensa la dirección x por 0*sizeof(int* [5][5][5])y desreferencia luego compensa esa dirección por 0*sizeof(int* [5][5]))
  • x[0][0][0]es la dirección de la primera matriz de 5 punteros a ints (compensación de dirección x por 0*sizeof(int* [5][5][5])y desreferenciación y compensación de esa dirección por 0*sizeof(int* [5][5])y compensación de esa dirección por 0*sizeof(int* [5]))
  • x[0][0][0][0]es el primer puntero a un int en la matriz (desplazar la dirección x por 0*sizeof(int* [5][5][5])y desreferenciar y compensar esa dirección por 0*sizeof(int* [5][5])y compensar esa dirección por 0*sizeof(int* [5])y compensar esa dirección por 0*sizeof(int*)y desreferenciar)
  • x[0][0][0][0][0]es el primer int señalado por el puntero a un int (desplazar dirección x por 0*sizeof(int* [5][5][5])y desreferenciar y compensar esa dirección por 0*sizeof(int* [5][5])y compensar esa dirección por 0*sizeof(int* [5])y compensar esa dirección por 0*sizeof(int*)y desreferenciar y compensar esa dirección por 0*sizeof(int)y desreferenciar)

En cuanto a la descomposición de la matriz:

void function (int* x[5][5][5]){
  printf("%p",&x[0][0][0][0]); //get the address of the first int pointed to by the 3d array
}

Esto es equivalente a pasar int* x[][5][5]o, int* (*x)[5][5]es decir, todos decaen a este último. Es por eso que no recibirá una advertencia del compilador para usar x[6][0][0]en la función, pero lo hará x[0][6][0]porque esa información de tamaño se conserva

void function (int* (*x)[5][5][5]){
  printf("%p",&x[0][0][0][0][0]); //get the address of the first int pointed to by the 3d array
}
  • x[0] es la dirección de la primera matriz 3D de punteros de 5x5x5 a ints
  • x[0][0] es la dirección de la primera matriz 2d de punteros 5x5 a ints
  • x[0][0][0] es la dirección de la primera matriz de 5 punteros a ints
  • x[0][0][0][0] es el primer puntero a un int en la matriz
  • x[0][0][0][0][0] es el primer int señalado por el puntero a un int

En el último ejemplo, es semánticamente mucho más claro de usar en *(*x)[0][0][0]lugar de x[0][0][0][0][0], esto se debe a que el primero y el último [0]aquí se interpretan como una desreferencia de puntero en lugar de un índice en una matriz multidimensional, debido al tipo. Sin embargo, son idénticos porque (*x) == x[0]independientemente de la semántica. También podría usar *****x, lo que parecería que está desreferenciando el puntero 5 veces, pero en realidad se interpreta exactamente igual: un desplazamiento, una desreferencia, una desreferencia, 2 desplazamientos en una matriz y una desreferencia, simplemente por el tipo está aplicando la operación a.

Esencialmente cuando usted [0]o *un *tipo de matriz no, es un desplazamiento y una desreferencia debido al orden de precedencia de *(a + 0).

Cuando [0]o *una *a un tipo de matriz, entonces es un desplazamiento a continuación, eliminar la referencia de un idempotente (al eliminar la referencia se resuelve por el compilador para producir la misma dirección - es una operación idempotente).

Cuando usted [0]o *un tipo con un tipo de matriz 1d es un desplazamiento y luego una desreferencia

Si usted [0]o **un tipo de matriz 2D es solo un desplazamiento, es decir, un desplazamiento y luego una desreferencia idempotente.

Si usted [0][0][0]o ***un tipo de matriz 3D es una desviación de compensación + idempotente, luego una desviación de compensación + idempotente, luego una desviación de compensación + idempotente y luego una desreferencia. La verdadera desreferencia solo ocurre cuando el tipo de matriz está completamente despojado.

Para el ejemplo del int* (*x)[1][2][3]tipo se desenvuelve en orden.

  • x tiene un tipo int* (*)[1][2][3]
  • *xtiene un tipo int* [1][2][3](offset 0 + desreferencia idempotente)
  • **xtiene un tipo int* [2][3](offset 0 + desreferencia idempotente)
  • ***xtiene un tipo int* [3](offset 0 + desreferencia idempotente)
  • ****xtiene un tipo int*(desplazamiento 0 + desreferencia)
  • *****xtiene tipo int(desplazamiento 0 + desreferencia)
Lewis Kelsey
fuente