
láser
Mi pregunta es: Si una variable de puntero tiene la misma dirección que su valor, ¿realmente se está apuntando a sí misma?
Por ejemplo, en el siguiente fragmento de código, es a
un puntero a sí mismo?
#include<stdio.h>
int main(){
int* a;
int b = (int)&a;
a = b;
printf("address of a = %d\n", &a);
printf(" value of a = %d\n", a);
}
Si a
no es un puntero a sí mismo, entonces la misma pregunta se plantea de nuevo: ¿Puede un puntero señalarse a sí mismo?
Además, ¿cómo es útil un puntero autoapuntador?
void* p = &p;
No es muy útil, pero las estructuras que apuntan a sí mismas son útiles en listas circulares de longitud 1:
typedef struct A {
struct A* next;
} A;
A a = { &a };
Según su ejemplo exacto, creo que quiso decir:
int* a;
int b = (int)&a;
a = (int*)b;
// which can be simplified to:
int* a = (int*)&a;

Leva
Lo que realmente estás haciendo allí es no que el puntero apunte a sí mismo. Eres usando el espacio de memoria asignado para el puntero para almacenar la ubicación del puntero. Un puntero a un int apunta a ints, nunca a otros punteros a ints, incluido él mismo.
Por ejemplo, supongamos que crea un puntero a
:
int * a;
Obtiene su propio lugar en la memoria:
4 a (5) 6
[....][00000000][....]
En este ejemplo simple, digamos que a está en la ubicación de memoria ‘5’.
Si hicieras esto:
a = (int*)&a;
… ocurriría lo siguiente:
4 a (5) 6
[....][00000005][....]
Lo que está pasando aquí es que a
está apuntando a lo que cree que es un número entero en la ubicación 5. Esta también es la misma ubicación de memoria que &a
está señalando, pero en el contexto de lo que a
está apuntando, ahora está apuntando al número entero en la ubicación 5, y ese número entero es 5.
Por ejemplo, ambos funcionarían:
cout<<(int)a;//outputs 5
cout<<*a;//Outputs the integer at memory location 5 - which is 5.
Si quisiera crear un puntero a a, definitivamente podría hacerlo, de cualquiera de estas formas:
int **b = (int**)a;
o
int ** b = &a;
Pero es muy importante darse cuenta de que a
no es un puntero a sí mismo. Es un puntero a la entero en la ubicación que almacena – que resulta ser lo mismo que su propia ubicación.
Para mostrar más (a través de un ejemplo aún más simple) lo que está pasando, algo similar podría pasar con un int
. Es decir, puede almacenar la ubicación de memoria de un int
dentro de sí mismo:
int a=999;
a
ahora tiene una ubicación en la memoria y tiene un valor de 999 (supondremos que se colocó en la ubicación de memoria ’46’):
45 a (46) 47
[....][00000999][....]
Está en la ubicación ’46’; si quisiéramos, podríamos almacenar este número como un número entero dentro a
:
a=(int)&a;
45 a (46) 47
[....][00000046][....]
y ahora a
es igual a &a
en valor, pero no en tipo – a
es solo un número entero, no apunta a sí mismo mágicamente ahora solo porque lo usamos para almacenar su propia ubicación de memoria.
Bueno, primero cambiaría el código:
int **a;
a = (int **)&a; // otherwise you get a warning, since &a is int ***
No estoy seguro de por qué harías esto, pero está permitido.
printf("The address of a is %p\n", &a);
printf("a holds the address %p\n", a);
printf("The value at %p is %p\n", a, *a); // the *a is why we made a an int **
Deberían imprimir lo mismo.
The address of a is 0x7fffe211d078
a holds the address 0x7fffe211d078
The value at 0x7fffe211d078 is 0x7fffe211d078
Tenga en cuenta que esta no es una buena idea, ya que el primer elenco a = (int **)&a
es un hack a la fuerza a
mantener un valor que no debería tener. Lo declaras un int **
pero trata de forzar un int ***
en ello. Técnicamente, los tamaños son los mismos, pero en general no hagas eso porque la gente espera que un int *
contiene la dirección de algo que se puede utilizar como int
etc.
Sí y no, porque el tipo de puntero es casi tan importante como el valor del puntero.
Sí, un puntero puede contener la posición de un puntero a sí mismo; incluso un long puede contener la posición de un puntero a sí mismo. (Ints generalmente puede hacerlo, pero no sé si eso está garantizado en todas partes).
Sin embargo, no hay ningún tipo para representar esta relación. Si tiene un puntero que apunta a sí mismo, en realidad tiene un tipo diferente cuando lo elimina. Entonces:
void *p = &p;
// *p is illegal, even though you probably wanted it to equal 'p'
if( *p != p ) {
printf("Something's wrong");
}
int *i = (int*)&i;
// The following statement is still illegal
if( *i == i ) {
printf("The universe works!");
}
Diría que la respuesta es ‘no’, porque no funcionará a menos que abuse del sistema de tipos. Creo que es una indicación de que estás haciendo algo mal (aunque a veces es ciertamente necesario).
Desreferenciar un puntero da como resultado un valor de su tipo de valor (por ejemplo, desreferenciar un int*
te da un int
un int*
tipo de valor s). Para que una variable apunte a un puntero, su tipo de valor tendría que ser int*
que no es el caso de un int*
Como se dijo anteriormente. Entonces, para que un puntero se apunte a sí mismo, tendría que hacer algún tipo de conversión para que el compilador lo obtenga:
int* a;
a = reinterpret_cast<int*>(&a);
desreferenciar a
entonces, tendrías un int
cuyo valor resulta ser la dirección en la que a
se encuentra (truncamiento mod de la dirección para adaptarse al tipo), pero sigue siendo un int
y no un int*
que requeriría otro elenco.
Un puntero a un puntero a menudo se conoce como un encargarse deque es de un tipo diferente (int**
) que un puntero (int*
). (Tenga en cuenta que un int**
el identificador tiene un tipo de valor int*
.)
Sí, un puntero puede señalarse a sí mismo como se menciona en las respuestas.
Un posible caso de uso es que podemos usar este truco en lugar de punteros NULL. Puede inicializar int * p = (int *)&p, y verificar esto más tarde para ver si el puntero es válido o no. Esto podría haberse usado si, por ejemplo, en un sistema en el que queríamos que 0x0 y todo el rango de direcciones fueran direcciones válidas.
También puede usar este truco en programas especiales de C que no fallarían con el uso del puntero NULL porque los evitaría por completo y el sistema de desreferencia no fallaría. Conducirá a un comportamiento erróneo, pero puede ayudar a la depuración en ciertas situaciones.

zaharpopov
Sí, es posible señalarse a sí mismo.
int* a;
a = &a;
Pero no tiene ningún uso, al menos explícitamente así.
gente, ¿por qué los negvotos? muy facil para ti??
– Lazer
28 de marzo de 2010 a las 6:43
Mi pregunta es… — una “duda” es algo completamente diferente.
– Éter
28 de marzo de 2010 a las 18:07
Aunque es legal, me pregunto qué hace realmente el compilador cuando se encuentra con algo como esto. Dado que el compilador realiza alguna optimización propia, apostaría a que la elimina. Pero, no podría decir con certeza.
– Natalia Adams
28 de marzo de 2010 a las 20:40
Aquí hay un enlace a esta pregunta: stackoverflow.com/questions/2532102/…
– amdn
12/03/2015 a las 20:59
@amdn Lo que necesita es un puntero a su propio comentario.
– bombomb007
1 de marzo de 2018 a las 14:24