2

Para mi entender: el puntero 1 esta direccionado a la estructura del puntero2 y el puntero2 esta direccionado al puntero3, pero no estoy muy segura. Alguno sabría como explicarlo mejor para poder entenderlo? Perdón por la pregunta tan básica.

Joel Muñoz Moran
  • 1,080
  • 7
  • 17
Emmaaaaa
  • 73
  • 9

2 Answers2

5

La sintaxis "flecha" como en:

a->b

sólo puede usarse si a es un puntero a un tipo struct, del cual b es un campo. El compilador lo convierte a esto otro, que es equivalente:

(*a).b

Es decir, se desreferencia el puntero a mediante *a, de modo que *a es la estructura a la que apuntaba, y entonces ya podemos acceder al campo b de esa estructura.

Puedes escribir (*a).b si te resulta más claro, pues es totalmente equivalente a a->b, siendo la segunda forma un simple syntactic sugar de la primera.

No obstante este sugar resulta útil cuando empiezas a tener campos de estructuras que son en realidad punteros a otras estructuras. Imagina en el ejemplo anterior que el tipo de b es también puntero a struct, y que quieres acceder al campo c de la estructura apuntada por b (el cual es un campo de la estructura apuntada por a).

La sintaxis explícita, desreferenciando los punteros, se vuelve farragosa:

(*(*a).b).c

si la lees con detenimiento entenderás lo que hace. La versión azucarada resulta en este caso mucho más legible:

a->b->c

Insisto sin embargo en un punto importante. Esta sintaxis no es para cualquier puntero, sino exclusivamente para punteros a estructuras, siendo lo que hay a la izquierda de la flecha el puntero y lo que hay a la derecha un campo de la estructura apuntada.

Por completar el ejemplo, esta sería una posible declaración de la variable a (naturalmente habría que inicializarla adecuadamente, pues sin la inicialización el intento de acceder a a->b daría probablemente un segfault).

struct demo {
   struct demo *b;
   int c;
} *a;
abulafia
  • 53,696
  • 3
  • 45
  • 80
  • Entonces en el caso de a->b->c seria un puntero apuntando a una estractura que apunta a otra estructura? – Emmaaaaa Feb 12 '19 at 19:27
  • Siendo un poco más precisos, sería un puntero apuntando a una estructura, que tiene un campo que es otro puntero que apunta a otra estructura. En el ejemplo que he puesto `a` apunta a una estructura, uno de cuyos campos es `b` que apunta a otra estructura (en este ejemplo, del mismo tipo que la primera), que tiene un campo llamado `c`. En este ejemplo no quise complicar más y dejé que `c` fuese `int`, pero podría ser puntero a otra estructura. En realidad esto también sería válido: `a->b->b->b->b->c` – abulafia Feb 12 '19 at 19:28
  • Ah,ahora lo entendi mejor,gracias. – Emmaaaaa Feb 12 '19 at 19:38
1

Supongamos que tenemos la estructura punto

struct punto {
    int x;
    int y;
}

Si una estructura grande va a ser pasada a una función, generalmente es más eficiente pasar un apuntador que copiar la estructura completa. Los apuntadores a estructuras son como los apuntantadores a variables ordinarias. La declaración

struct punto *ap

dice que ap es un apuntador a una estructura de tipo struct punto. Si ap apunta a una estructura punto, *ap es la estructura, y (*ap).x y (*ap).y son los mienbros. Para emplear ap, se podría escribir, por ejemplo,

struct punto origen, *ap

ap = &origen;
printf("el origen es (%d, %d)\n", (*ap).x, (*ap).y);

Los paréntesis son necesarios en (*pp).x debido a que la precedencia del operador miembro de estructura . es mayor que la de *. La expresión *pp.x significa *(pp.x), lo cual es ilegal debido a que x no es un apuntador.

Ahora, los apuntadores a estructuras se usan con tanta frecuencia qeu se ha proporcionado una notación alternativa como abreviación. Si p es un apuntador a estructura, entonces:

p -> miembro de estructura

se refiere al miembro en particular. (El operador -> es un signo menos seguido por >). De esta manera podríamos haber esfrito

printf("el origen es (%d, %d)\n", ap->x, ap->y);
Marco Ramírez
  • 645
  • 5
  • 11