Converting int to int* then back to int
I am missing something obvious here but consider the following,
int k = 10;
int *p = &k;
int i = (int)p;
above produces,
warning: cast from pointer to integer of different size
and following,
int k = 10;
int *p = &k;
int i = p;
causes,
warning: initialization makes integer from pointer without a cast
a bit of googling lead me to,
Converting a pointer into an 开发者_运维知识库integer
which advices using uintptr_t,
int k = 10;
int *p = &k;
int i = (uintptr_t)p;
above works no errors no warnings. So my question is k is an int and p is an int pointer pointing to k why do i get an error dereference p?
int k = 10;
int *p = &k;
int i = *p;
Note the * before p on the last line. Dereference the pointer to get the int it points to.
EDIT: I'm not very familar with uintptr_t, but I ran the code int i = (uintptr_t)p; The result that is stored into i is the memory address of k, not 10. The cast tells the compiler that you really want to turn the address into an integer (so there's no warning; because you are insisting to the compiler that you know what you are doing) but does not dereference the pointer.
You get an error because you didn't actually dereference p
, you just casted it (forcefully changed its type) from int*
. To dereference, you need to use the *
operator, like so:
int i = *p;
You aren't dereferencing the pointer, so you are assigning the address of the pointer to an int.
int i = *p;
Is what you most likely wanted.
You're playing with int to pointer casting, and that has no guarantee that the two even use the same amount of memory anymore. Actually it didn't have a guarantee of using the same size back when people did it, but for most platforms it just happened to work anyway.
Since you explicitly cast in the latter example, the compiler assumes it wasn't a mistake (or why would you have typed it out?). That's the reason for the difference in compiler output.
Note that if you didn't want to store the memory address of k into i, then the proper way to get K's value into i would be
int i = *p;
You are setting i
equal to the address of k
(which is what p
holds). And the address value is an unsigned type. So when casting from the pointer, it complains because you are taking casting and unsigned value to signed.
Also pointers are different sized types based on the platform, so 32 bit pointers are smaller than 64. So if the pointer is a 8 byte unsigned, you are casting it down to a 4 byte signed.
this is how it should look
int k = 10;
int *p = &k;
int i = *p;
here is how I think of it
k = 10
p = some address
&k = some address
*p = 10
uintptr_t
is not meant as a type to do an intermediate cast to int
but used as such. If it is defined on a system (and yours seems to have it) it is the unsigned integer type where you don't loose information when you load it with a pointer value. So if you must, use uintprt_t
fully instead of int
. But this should be rare occasions, and in most cases I would bet, this is just a sign of bad design.
In any case int
is a bad idea from the start. If anything, a pointer value is just an position in a virtual memory space and seeing it as a signed value makes no sense to me at all.
精彩评论