开发者

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;

Why does this code using pointers not retrieve the value of x using b?

int *a = &x;    //address of x is 0x33

Why does this code using pointers not retrieve the value of x using b?

Int * b = (int *) &a;     //address of a is 0x34

Why does this code using pointers not retrieve the value of x using b?

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 accessbit as a pointer to a pointer to an integer in (**b). It is not allowed. To do so you need to typecast the value ofb` 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜