Dirección de puntero en una matriz multidimensional

Estoy jugando con multidimensionales los arrays y punteros. He estado mirando un programa que imprime el contenido de, y las direcciones de una matriz simple. Aquí está mi declaración de matriz:

int zippo[4][2] = { {2,4},
            {6,8},
            {1,3},
            {5,7}   };

Mi comprensión actual es que zippo es un puntero, y puede contener la dirección de un par de punteros. De forma predeterminada, zippo contiene la dirección de puntero zippo[0], y también puede contener las direcciones de los punteros zippo[1], zippo[2], y zippo[3].

Ahora, veamos la siguiente declaración:

printf("zippo[0] = %p\n", zippo[0]);
printf("  *zippo = %p\n", *zippo);
printf("   zippo = %p\n", zippo);

En mi máquina, que da el siguiente resultado:

zippo[0] = 0x7fff170e2230
  *zippo = 0x7fff170e2230
   zippo = 0x7fff170e2230

Puedo entender perfectamente por qué zippo[0] y *zippo tienen el mismo valor. Ambos son punteros, y que tanto el almacén de la dirección (por defecto) del entero 2, o zippo[0][0]. Pero lo que es con zippo además de compartir la misma dirección de memoria? No zippo a almacenar la dirección del puntero zippo[0]? Whaaaat?

  • En realidad, nunca he tocado Java. Me habló de mis dedos de los pies en el agua con BASIC y pascal, luego saltó a la derecha con C. C es el primer y único idioma que yo realmente has intentado aprender. Lo que, Java es mucho más alto nivel, y por lo tanto no necesita lidiar con este nivel de detalle?
InformationsquelleAutor Ichimonji10 | 2010-01-05

5 Kommentare

  1. 31

    Cuando se declara una matriz multidimensional, el compilador trata como una sola matriz bidimensional. Matrices multidimensionales son sólo una abstracción para hacer nuestra vida más fácil. Tienes un malentendido: Esto no es un vector que apunta a 4 matrices, siempre es de un solo contigous bloque de memoria.

    En su caso, a hacer:

    int zippo[4][2]

    Es realmente lo mismo que hacer

    int zippo[8]

    Con las matemáticas que se requieren para el 2D abordar manejado por el compilador.

    Para más detalles, consulte este tutorial sobre Matrices en C++.

    Esto es muy diferente que hacer:

    int** zippo

    o

    int* zippo[4]

    En este caso, usted está haciendo una serie de cuatro de los punteros, que se podría destinar a otras matrices.

    • Ahhh, esta es una explicación muy clara. Gracias. Voy a leer un poco sobre la diferencia entre una simple matriz multidimensional (siendo un único bloque contiguo de memoria) y una matriz de punteros.
  2. 33

    Cuando una expresión de matriz aparece en la mayoría de los contextos, su tipo se convierte implícitamente de «N-elemento de la matriz de T» a «puntero a T», y su valor se establece a punto para el primer elemento de la matriz. Las excepciones a esta regla: cuando la matriz de expresión es un operando de la sizeof o en la dirección de (&) los operadores, o cuando la matriz es un literal de cadena ser utilizado como un inicializador en una declaración.

    Por lo tanto, la expresión zippo «decae» de tipo int [4][2] (4-elemento de la matriz de 2 elementos de las matrices de int) a int (*)[2] (puntero a 2-elemento de la matriz de int). Del mismo modo, el tipo de zippo[0] es int [2], que se convierte de forma implícita a int *.

    Dada la declaración de int zippo[4][2], la siguiente tabla muestra los tipos de diferentes de la matriz de expresiones relacionadas con zippo y cualquier conversiones implícitas:

    Tipo de expresión convierte de forma Implícita a la expresión Equivalente 
    ---------- ---- ----------------------- --------------------- 
    zippo int [4][2] int (*)[2] 
    &zippo int (*)[4][2] 
    *zippo int [2] int * zippo[0] 
    zippo[i] int [2] int * 
    &zippo[i] int (*)[2] 
    *zippo[i] int zippo[i][0] 
    zippo[i][j] int 
    &zippo[i][j], int * 
    *zippo[i][j] no válido 
    

    Nota que zippo, &zippo, *zippo, zippo[0], &zippo[0], y &zippo[0][0] todos tienen el mismo valor; todas ellas apuntan a la base de la matriz (la dirección de la matriz es la misma que la dirección del primer elemento de la matriz). Los tipos de las diversas expresiones que todos difieren, sin embargo.

    • Esto realmente ayuda con mi entendimiento de cómo muchas maneras, una matriz o un puntero puede ser representado, y lo que significa para una declaración a la caries. Muy completo. Gracias.
  3. 5

    zippo no es un puntero. Es una matriz de valores de matriz. zippo, y zippo[i] para i en 0..4 puede «decaimiento» a un puntero en algunos casos (sobre todo, en el valor de los contextos). Intente imprimir sizeof zippo para un ejemplo del uso de zippo en un no-valor de contexto. En este caso, sizeof le informe el tamaño de la matriz, no el tamaño de un puntero.

    El nombre de una matriz, en valor contextos, decae a un puntero a su primer elemento. Así, en el contexto de valor, zippo es el mismo que &zippo[0], y por lo tanto es de tipo «puntero a una matriz [2] de int«; *zippo, en el contexto de valor es el mismo que &zippo[0][0], es decir, «puntero a int«. Tienen el mismo valor, pero de diferentes tipos.

    Recomiendo la lectura de Matrices y Punteros para responder a su segunda pregunta. Los punteros tienen el mismo «valor», pero el punto de diferentes cantidades de espacio. Intente imprimir zippo+1 y *zippo+1 a ver con mayor claridad:

    #include <stdio.h>
    
    int main(void)
    {
        int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} };
        printf("%lu\n", (unsigned long) (sizeof zippo));
        printf("%p\n", (void *)(zippo+1));
        printf("%p\n", (void *)(*zippo+1));
        return 0;
    }

    Para mi carrera, imprime:

    32
    0xbffede7c
    0xbffede78

    Me dice que sizeof(int) en mi máquina es de 4, y que el segundo y el tercer punteros no son iguales en valor (como se esperaba).

    También, "%p" especificador de formato de necesidades void * en *printf() funciones, por lo que deben emitir su punteros a void * en su printf() llamadas (printf() es un variadic función, por lo que el compilador no puede hacer la conversión automática para usted aquí).

    Editar: Cuando digo una matriz «decae» a un puntero, me refiero a que el nombre de un array en el contexto de valor es equivalente a un puntero. Por lo tanto, si tengo T pt[100]; para algún tipo T, a continuación, el nombre de pt es de tipo T * en el valor de los contextos. Para sizeof y unario & operadores, el nombre pt no se reducen a un puntero. Pero usted puede hacer T *p = pt;—esto es perfectamente válido, porque en este contexto, pt es de tipo T *.

    Tenga en cuenta que esta «decadencia» que sucede sólo una vez. Así que, digamos que tenemos:

    int zippo[4][2] = { {2,4}, {6,8}, {1,3}, {5,7} };

    Entonces, zippo en el contexto de valor decae a un puntero de tipo: puntero a la matriz[2] de int. En el código:

    int (*p1)[2] = zippo;

    es válido, mientras que

    int **p2 = zippo;

    activará un «incompatible asignación de puntero» de advertencia.

    Con zippo se define como el anterior,

    int (*p0)[4][2] = &zippo;
    int (*p1)[2] = zippo;
    int *p2 = zippo[0];

    son todas válidas. Se debe imprimir el mismo valor cuando se imprimen utilizando printf("%p\n", (void *)name);, pero los punteros son diferentes en el sentido que apuntan a la totalidad de la matriz de una fila, y un solo entero, respectivamente.

    • Vamos a ver si tengo este derecho: a pesar de que zippo y zippo[0] punto para diferentes cantidades de memoria, su dirección de partida es el mismo, y en el valor de los contextos de que ambos apuntan a la primera entero en el zippo. La correcta? Y, es que lo que quieres decir por «decadencia»?
    • No. zippo[0] en el valor de los contextos es int *, y apunta a la primera entero, donde zippo en el valor de los contextos es «puntero a una matriz [2] de int«. Usted podría hacer: int (*p)[2]; p = zippo; por ejemplo. Entonces, p[0] == 2 y p[1] == 4. Para la «decadencia», ver a mi (que pronto aparecerá) edit.
  4. 2

    La cosa importante aquí es que int zippy[4][2] no es el mismo tipo de objeto como int **zippo.

    Igual int zippi[5], zippy es la dirección de un bloque de memoria. Pero el compilador sabe que usted desea abordar las ocho de la localización de memoria partir de zippy con un dos dimensiones de la sintaxis, pero queremos abordar las cinco de la localización de memoria partir de zippi con una dimensiones de la sintaxis.

    zippo es una cosa completamente diferente. Se contiene la dirección de un bloque de memoria lo suficientemente grande como para contener dos puntero, y si usted hace ellos punto en algunas matrices de enteros, se puede eliminar con las dos dimensiones de la matriz de la sintaxis de acceso.

  5. 2

    Muy bien explicado por Reed, voy a agregar unos puntos más para hacerlo más sencillo, cuando nos referimos a zippo o zippo[0] o zippo[0][0], todavía estamos refiriendo a la misma dirección de la base de la matriz zippo. La razón de ser de las matrices son siempre bloque contiguo de memoria y matrices multidimensionales son múltiples dimensiones de las matrices continuamente colocado.

    Cuando se tiene que el incremento por cada fila, se necesita un puntero int *p = &zippo[0][0], y haciendo p++ incrementa el puntero por cada fila.
    En el ejemplo de identificación de un 4 X 2 de la matriz, haciendo p++ su puntero que señala a la segunda serie de 4 elementos.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea