[C con Clase] Punteros a miembros de estructuras

Vicent vginer en gmail.com
Vie Abr 9 19:20:00 CEST 2010


2010/4/9 Steven Davidson <srd4121 en njit.edu>:
> Hola Vicent,
>
> Sí. El código que has escrito es correcto. Esto es así porque estás
> accediendo a la memoria de una variable existente de una estructura también
> existente. Es decir, 'cosa' es una variable de tipo 'Cosa' y por tanto sus
> miembros son variables que también existen.
>
> El capítulo 41 del curso habla de punteros a miembros sin que aún existan en
> memoria tales miembros. Usando tu ejemplo, esto sería:
>
> double Cosa::*precio = &Cosa::b;
>
> Como puedes ver, no estamos usando variables. 'Cosa' es el tipo de la
> estructura. Técnicamente, estos "punteros" realmente son desplazamientos a
> partir del comienzo de la estructura. Al combinar este tipo de puntero a
> miembro con una variable existente, podemos acceder al miembro sin usar su
> nombre definido. Por ejemplo,
>
> Cosa una_cosa;
> BYTE *ptr = reinterpret_cast< Cosa * >( una_cosa );
> double *precio = reinterpret_cast< double * >( ptr+sizeof(double) );
>
> El miembro 'a' es el primer miembro en la estructura y por tanto siempre
> estará al principio, por lo que estará a 0 bytes de desplazamiento a partir
> de la variable de la estructura. En nuestro ejemplo,
>
> &una_cosa == &una_cosa.a
>
> Digamos que 'una_cosa' está en la dirección de memoria: 0xAA33FF00.
>
> El miembro 'b' es el segundo miembro en la estructura y por tanto siempre
> estará a 'sizeof(double)' de la estructura, porque 'a' ocupa
> 'sizeof(double)' bytes. Es decir,
>
> &una_cosa + sizeof(double) == &una_cosa.b
>
> Mirando las direcciones de memoria, tenemos que,
>
> &una_cosa.b = 0xAA33FF00 + 8 = 0xAA33FF08
>
> (Nota: suponemos que 'double' ocupa 8 bytes).
>
> Por último, el miembro 'c' es el tercer miembro de la estructura. Acabamos
> con la siguiente dirección de memoria:
>
> &una_cosa.c = 0xAA33FF00 + 16 = 0xAA33FF10
>
> Por lo tanto, podemos referir a cada miembro al conocer su dirección de
> memoria relativa a la de la variable de la estructura. De hecho, existen
> macros en ANSI C para este tipo de cosas llamada 'offsetof()' en <stddef.h>
> o en C++ se llama <cstddef>. Puedes echar un vistazo yendo a:
> http://c.conclase.net/librerias/?ansilib=stddef#inicio
>
> En C++, este comportamiento forma parte del lenguaje y por tanto, no
> usaríamos 'offsetof()'. Sin embargo, el mecanismo es técnicamente el mismo,
> pero obviamente C++ controla la concordancia de tipos, porque como todos
> sabemos, C++ es un lenguaje fuertemente tipificado.
>
> Al hacer,
>
> double Cosa::*precio = &Cosa::b;
>
> Técnicamente, 'precio' no es un puntero de verdad sino más bien un
> desplazamiento. Obviamente, necesitamos una variable para combinarla con
> 'precio' porque la variable tiene una dirección de memoria "verdadera". Por
> ejemplo,
>
> una_cosa.*precio = 10.43;
>
> Esto es una forma indirecta de referirnos a 'una_cosa.b'. En este sentido,
> se parece a un puntero, por la indirección.
>
>
> Espero haber aclarado el tema.
>

Steven:

Sí, me has aclarado muchísimo el tema. He programado algo parecido al
ejemplo que yo he puesto (punteros que apuntan a miembros de una
estructura), pero después casualmente he llegado al capítulo 41 del
curso C++ Conclase y me han entrado las dudas de si lo que había hecho
estaría bien o no.

No había caído en la diferencia que apuntas: yo creo punteros a
elementos concretos ya existentes.

Muchas gracias. En esta lista se aprende.

--
Vicent




Más información sobre la lista de distribución Cconclase