Why does this code using pointers not retrieve the value of x using b?
#include <stdio.h>
int main (){
int x=10,*a=&x;
int *b=(int *)&a;
printf("%d %d %d %d %d %d ",x,a,*a,b,*b,**b);
return 0;
}
In this little program variable x
is assigned value 10
and then address of x
is assigned to pointer variable a
. Now proper way is int **b=&a
because b
should be a pointer to pointer. But I thought it's ultimately the address which gets stored. So to store address of a
to an int pointer b
, I use typecasting int *b=(int *)&a
. Now address of a
got stored in b
. So if I use *b
, it give identical result as a
.
But when I extend this further to **b
it doesn't give the same result as *a
which I expected. In fact it gives an er开发者_运维百科ror. *b
and a
are same so when i ask to retrieve from this value like **b
and *a
this doesn't work. For this I assumed a concept that *b
and a
are same in value but they are different in type. The value given by a
is pointer and value given by *b
is an integer so **b
is not possible like *a
.
But I still think that it should work.
I am using Dev C++ 4.9.9.2 which is a 32 bit compiler. The memory allocated to an int
and int *
is the same, that is 4 bytes. And *b
and a
have same bit representation also. So when I write *(*b)
I used same value as in *(a)
. But what is the preventing factor? The format is like *(some bit representation)
and the bit representation is identical in case of *b
and a
. So the value of x
should be retrieved. Please explain the preventing factor.
It seems to work fine for me, once your variable declarations are cleaned up a bit:
int main (){
int x = 10;
int* a = &x;
int** b = &a;
printf("%d %d %d %d %d %d ",x,a,*a,b,*b,**b);
return 0;
}
I'd suggest that the problem is that you declared b
with the wrong type (and then cast &a
into that type). It is not an int*
, it is an int**
, i.e. a pointer to a pointer to an integer. You could of course cast *b
to the desired type in your printf()
statement, but why not just declare it correctly in the first place?
Here's an ideone example: http://ideone.com/idwfd
int x= 10;
int *a = &x; //address of x is 0x33
Int * b = (int *) &a; //address of a is 0x34
So from the above we have that:
- x = 10 a = 33
- *a = 10 b = 34
- *b = 33
- * (int *) *b = 10
- **b would result in a compilation error
*b
is an integer, and you're not allowed to apply the unary *
to an integer. (How would the compiler know whether you expected the bit pattern to point to an int, char, short, or whatever?) You can cast the integer back to a pointer and then deference it: *(int*)*b
, which should do what you expect.
Let's look at what happens here. a
is a pointer to int
. We take the address of a
, which is a pointer to pointer to int
, cast that to a pointer to int
, and assign it to b
.
Then we dereference b
twice. b
is a pointer to int
, so *b
is an int
. Then we dereference an int
. Wait, you can't dereference an int
- it's not a pointer. And so we enter the twilight zone of undefined behavior.
**b
would point to the correct block of memory, but the compiler doesn't have the proper type information. @Henning says, dereferencing b
once is an int
value according to the compiler, and there's no dereference operator for type int
. That's specifically why the int**
and its ilk exist: to tell the compiler how many dereferences are possible/necessary.
Out of curiosity is there a reason int* b = a;
doesn't work, if you do want the value of x
after one dereference?
+----------+ +----------+ +----------+
| 10 | | addr_x | | addr_a |
+----------+ +----------+ +----------+
| x | | a | | b |
+----------+ +----------+ +----------+
| addr_x | | addr_a | | addr_b |
+----------+ +----+-----+ +----+-----+
^ ^ | ^ |
| +----(*a)-------+ +----(*b)---+
| |
+----------------(**b)-------------+
The access is like above.
You have told the compiler that the pointer b
is a pointer to an integer. When you do *b
it dereferences to an int
and another indirection is not possible on type of int and therefore when you access
bit as a pointer to a pointer to an integer in (
**b). It is not allowed. To do so you need to typecast the value of
b` to the correct type and use it.
You want to use the value of *b
as an address and fetch the int value stored at the address location *b
. Therefore You want *b
to be an int *
which makes b
an (int **) . Therefore it is best to declare b
as int **b;
. In your case before applying the double indirection typecast b
to be int **
and then use double indirection.
printf ("%x", **((int **)b));
This will interpret the value stored in b
as a pointer to a pointer to an integer and then fetch the value of x
as you want.
精彩评论