2011-02-11 31 views
5

estoy perdiendo algo obvio aquí pero tenga en cuenta lo siguiente,conversión de int a int * a continuación, volver a int

int k = 10; 
int *p = &k; 
int i = (int)p; 

anterior produce,

warning: cast from pointer to integer of different size 

y siguientes,

int k = 10; 
int *p = &k; 
int i = p; 

causas,

warning: initialization makes integer from pointer without a cast 

un poco de google me llevan a,

Converting a pointer into an integer

el cual asesora usando uintptr_t,

int k = 10; 
int *p = &k; 
int i = (uintptr_t)p; 

anterior funciona sin errores no hay advertencias. Entonces mi pregunta es k es un int y p es un puntero int que apunta a k ¿por qué obtengo una desreferencia de error p?

+0

¿Qué esperas que sea el valor de 'i'? –

+0

No desreferencia 'p' en ninguno de sus ejemplos. ¿Puedes aclarar tu pregunta? – nmichaels

Respuesta

9
int k = 10; 
int *p = &k; 
int i = *p; 

Tenga en cuenta el * antes p de la última línea. Dereference the puntero para obtener el int al que apunta.

EDITAR: No estoy muy familiarizado con uintptr_t, pero ejecuté el código int i = (uintptr_t) p; El resultado que se almacena en i es la dirección de memoria de k, no 10. La conversión le dice al compilador que realmente desea convertir la dirección en un número entero (por lo que no hay advertencia, porque está insistiendo en el compilador que conoce lo que estás haciendo) pero no desreferencia el puntero.

+0

gracias por la aclaración, pero ¿por qué el tercer ejemplo no procesa ningún error? –

+1

@Hamza Yerlikaya: En primer lugar, ninguno de sus ejemplos produjo ningún * error * (aunque deberían tenerlo). Ellos produjeron * advertencias *. En segundo lugar, la advertencia es autoexplicativa: el tamaño de 'int' es diferente del tamaño de' int * '. El tamaño de 'uintptr_t' es el mismo que el tamaño de' int * ', por lo tanto, no hay advertencia en ese caso. – AnT

3

Obtiene un error porque en realidad no eliminó la referencia p, acaba de convertirlo (cambió su tipo de forma forzada) de int*. Para eliminar la referencia, es necesario utilizar el operador *, así:

int i = *p; 
2

Usted no se dereferencing el puntero, por lo que está asignando la dirección del puntero a un int.

int i = *p; 

Es lo que más deseaba.

1

Está jugando con int pointer casting, y eso no garantiza que los dos usen la misma cantidad de memoria. En realidad, no tenía la garantía de usar el mismo tamaño cuando la gente lo hacía, pero para la mayoría de las plataformas simplemente funcionaba de todos modos.

Como explícitamente echaste el último ejemplo, el compilador supone que no fue un error (¿o por qué lo habrías tipeado?). Esa es la razón de la diferencia en la salida del compilador.

Tenga en cuenta que si no desea almacenar la dirección de memoria de k en i, entonces la forma apropiada para obtener el valor de K en yo estaría

int i = *p; 
0

esto es cómo debe mirar

int k = 10; 
int *p = &k; 
int i = *p; 

aquí es lo que pienso de ella

k = 10

p = alguna dirección

& k = alguna dirección

* p = 10

1

Usted está configurando i igual a la dirección de k (que es lo que sostiene p). Y el valor de la dirección es un tipo sin firmar. Por lo tanto, al lanzar desde el puntero, se queja porque está tomando el lanzamiento y el valor sin signo para firmar.

También los punteros son de diferentes tamaños según la plataforma, por lo que los punteros de 32 bits son más pequeños que 64. Por lo tanto, si el puntero es de 8 bytes sin signo, lo está lanzando a un byte de 4 bytes.

0

uintptr_t no se entiende como un tipo para hacer un molde intermedio a int pero se usa como tal. Si está definido en un sistema (y el suyo parece tenerlo), es el tipo de entero sin signo en el que no pierde información cuando lo carga con un valor de puntero. Por lo tanto, si debe hacerlo, use uintprt_t en lugar de int. Pero esto debería ser en raras ocasiones, y en la mayoría de los casos, apostaría, esto es solo un signo de mal diseño.

En cualquier caso, int es una mala idea desde el principio. En todo caso, un valor de puntero es solo una posición en un espacio de memoria virtual y verlo como un valor firmado no tiene ningún sentido para mí.