2011-06-24 15 views
12

Teniendo en cuenta que el nombre de un array es en realidad un puntero al primer elemento de una matriz, el siguiente código:¿Diferencia entre puntero a puntero y puntero a matriz?

#include <stdio.h> 

int main(void) 
{ 
    int a[3] = {0, 1, 2}; 
    int *p; 

    p = a; 

    printf("%d\n", p[1]); 

    return 0; 
} 

impresiones 1, como se esperaba.

Ahora, dado que yo puedo crear un puntero que apunta a un puntero, escribí lo siguiente:

#include <stdio.h>                

int main(void)                 
{                    
     int *p0;                 
     int **p1;                
     int (*p2)[3];               
     int a[3] = {0, 1, 2};             

     p0 = a;                 
     p1 = &a;                 
     p2 = &a;                 

     printf("p0[1] = %d\n(*p1)[1] = %d\n(*p2)[1] = %d\n",      
         p0[1], (*p1)[1], (*p2)[1]);        

     return 0;                
} 

esperaba que compilar e imprimir

p0[1] = 1 
(*p1)[1] = 1 
(*p2)[1] = 1 

Pero en cambio, se va mal en tiempo de compilación, decir:

test.c: In function ‘main’: 
test.c:11:5: warning: assignment from incompatible pointer type [enabled by default] 

¿Por qué esa asignación es incorrecta? Si p1 es un puntero a un puntero a un int y a es un puntero a un int (porque es el nombre de una serie de int s), ¿por qué no puedo asignar a &ap1?

+1

Hace algún tiempo escribí [una respuesta a una pregunta similar] (http://stackoverflow.com/questions/5181237/confusion-in-data-types-in-a-2d-array) que podría gustarle. – pmg

+0

¡Gracias por la pista! – jpmelos

Respuesta

16

línea 11 es

 p1 = &a; 

donde p1 tiene tipo int ** y a tiene el tipo int[3], ¿verdad?

Bueno; &a tiene tipo int(*)[3] y ese tipo no es compatible con int** como el compilador te dijo

Es posible que desee probar

 p1 = &p0; 

Y leer the c-faq, en particular la sección 6.

En resumen: matrices no son punteros, y punteros no son matrices.

+1

Ese tipo de subvierte todo lo que pensé que sabía sobre matrices y punteros. Me pregunto cómo me salí con esto durante tantos años, realmente. Gracias por dejarlo en claro. – jpmelos

+1

@jpmelos - La forma en que funcionan las matrices y punteros es sorprendentemente sutil, y no es algo que sea muy fácil de dejar en claro al principio del aprendizaje C. Me alegra que lo haya conseguido. –

+1

Se salió con la suya porque muy a menudo las matrices se comportan como punteros y punteros se comportan como matrices ... ** ¡pero no son lo mismo! ** Lea [la c-faq] (http://c-faq.com /) sección 6: es realmente interesante :) – pmg

0

Para muchas operaciones, a implica y ambas devuelven lo mismo: la dirección del primer elemento en la matriz.

No puede obtener la dirección del puntero porque la variable no almacena el puntero. a no es un puntero, aunque en algunos casos se comporta como uno.

+0

Entonces, ¿por qué 'p2 = & a' funciona y' p1 = & a' no? – jpmelos

+2

@jpmelos - Porque el tipo de '& a' es' int (*) [3] 'en lugar de' int ** '. –

+4

¡No! 'a' no implica' & a' para muchas cosas. ¡Implica '& a [0]'! – nos

6

a no es un puntero a int, se desintegra a tales en ciertas situaciones. Si &a fue del tipo int **, no podría usarlo para inicializar p2, ¿verdad? Para obtener el efecto que desee, debe hacer p1 = &p0;. "puntero a puntero" significa "en esta dirección, encontrará un puntero". Pero si nos fijamos en la dirección &a, encontrará una matriz (obviamente), por lo que int ** no es del tipo correcto.

+0

Entonces, ¿qué se almacena bajo el nombre 'a', si no una dirección para el primer elemento de' a' (que sería el puntero que estaba buscando)? – jpmelos

+3

@jpmelos - 'a' es una matriz. Almacena los elementos reales de la matriz. El nombre de una matriz se desintegra a un puntero al primer elemento cuando se pasa a una función, pero eso no significa que las matrices se implementen como punteros a un área. 'int a [3];' por sí solo no hace punteros, solo tres 'int's. –

+0

¡Muchas gracias! ¡Tu comentario me ayudó a iluminar mis pensamientos un poco más! – jpmelos