Reputation: 94
struct node
{
int a;
};
int main()
{
struct node y = {23};
struct node *x = &y;
return 0;
}
Here is some code i came across, i messed around with the code and found out that "&x" has type pointer to pointer. I am very confused on how this could be so i drew it out and made a program to try and find out how below, x has address 0x123 and y has address 0x24:
My understanding is &x
returns the address of the pointer x, *&x
returns the address that x
points too, IT RETURNS A ADDRESS NOT ANOTHER POINTER. So how is the type a pointer to pointer? As far as i can see:
Lastly here is my program that illustrates this and further confuses me because what i thought is correct in the program:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
struct node
{
int a;
};
int main()
{
struct node y = {23};
struct node *x = &y;
printf("\n\nstruct node y = {23}\nstruct node *x = &y;\n\n");
printf("address of x is: %p\naddress of y is: %p\n", &x, &y);
printf("\n&x address is: %p\n", &x);
printf("*&x address is: %p\n", *&x);
}
The output of this program looks like this:
struct node y = {23}
struct node *x = &y;
address of x is: 0x7ffdedcc2da0
address of y is: 0x7ffdedcc2d9c
&x address is: 0x7ffdedcc2da0
*&x address is: 0x7ffdedcc2d9c
What i though was correct and comparing it to my diagram shows it is correct.
Upvotes: 2
Views: 311
Reputation: 223768
The unary &
operator gives a pointer to its operand. &thing
is a pointer to thing
.
If x
is a pointer to a struct node
, then &x
is a pointer to a pointer to a struct node
.
My understanding is
&x
returns the address of the pointerx
,*&x
returns the address thatx
points [to]…
No, *&x
gives x
.
Unary *
is the opposite of unary &
. *&thing
is thing
.
Whatever thing
is, &thing
is a pointer to thing
. And, given a pointer, such as &thing
, *
gives whatever the pointer points to. Since &thing
points to thing
, *&thing
is thing
.
Upvotes: 3
Reputation: 61635
My understanding is &x returns the address of the pointer x, *&x returns the address that x points too, IT RETURNS A ADDRESS NOT ANOTHER POINTER. So how is the type a pointer to pointer? As far as i can see:
Let's walk through this step by step and make sure we are being precise about all the terminology.
x
is of type struct node *
, i.e., a pointer-to-node. It is, therefore, a pointer.
&x
is an expression (in the same way that 1 + 2
is an expression). Expressions do not "return" anything; they evaluate to some result which has a value and a type. In this case, we apply the &
operator to x
. The resulting value has a type of pointer-to-pointer-to-node (in C syntax, struct node**
). You don't need to do any difficult thinking to understand this: the type that results from &
is pointer-to-(whatever was the type of the thing that &
is applied to). In our case, the (whatever was the type of the thing that &
is applied to) is "pointer-to-node", and we directly substitute that in: typeof(&x)
is (typeof x)*
which is (struct node *)*
which is struct node **
. (I don't think you can actually use (typeof x)*
as a type declaration; I'm just showing the type calculus here in something that looks vaguely C-ish.)
The value of that expression is the address of the existing x
variable. That's what &
does. The issue here is that "a address not another pointer" makes no sense, because "address" isn't a different kind of type. When we say "the address of x", we mean "a thing which has a type that is pointer-to-(whatever is the type of x), and a value which tells us where x is located in memory".
When we write *&x
, that is another expression, in which we apply the *
operator to the subexpression &x
. Functionally, *
undoes the effect of &
; it means "the thing at the specified location", and the type has one level of "pointer-to" removed.
de-referencing x is the same as *x which is of type (struct node *)
Careful with your language. *x
indeed "is the same as dereferencing x", which is to say, it is the way that we express that idea in code. x
is a pointer of type struct node *
; thus, *x
is the pointed-at value, of type struct node
.
printf("\n&x address is: %p\n", &x);
printf("*&x address is: %p\n", *&x);
I think this is where you confused yourself. The thing that you labelled as "&x address"
is not the address of &x
, but instead &x
itself, i.e. the address of x
. (Just like how in the first printf
you printed the very same thing - &x
- and labelled it "address of x".) Of course printing *&x
gives you the same thing as printing &y
, because *&x
is just x
(the *
undoes the &
), which is &y
(because that's how x
was initialized). You can do this kind of reasoning without even needing to think about the types (although you will need to think about types in the long run, in order to write correct code).
There are, of course, limitations: you cannot just write pairs of &
and *
together as much as you want and have them cancel out. *
needs to be applied to something that is a pointer, and using &
later can't save you from that requirement. Similarly, &
needs to be applied to something that has a defined location, and using *
later can't save you from that requirement. In particular, you can't apply consecutive &&
to something, because the address produced by the first &
is temporary and doesn't conceptually have an address (in the compiled code, it might for example only ever appear in a register and never be written to memory).
Upvotes: 4
Reputation: 224822
Generally speaking, if a variable n
has type foo
, then the address of that variable, i.e. &n
has type foo *
i.e. a pointer to foo
.
All variables have an address, including pointer variables. So if m
has type foo *
i.e. pointer to foo
, then &m
has type foo **
i.e. pointer to pointer to foo
.
In your example, x
has type struct node *
. It contains &y
i.e. the address of y
. And since y
has type struct node
its address has type struct node *
. If you were to print x
you would see that it has the same value as &y
.
Also, when the indirection operator *
is applied to the result of the address-of operator &
they cancel each other out. So the expression *&x
is exactly equivalent to the expression x
.
Addressing your specific points:
x is a pointer
Correct, as it is declared with a pointer type
de-referencing x is the same as *x which is of type (struct node *)
Dereferencing x
is exactly *x
, however since x
already has type struct node *
that means that *x
has type struct node
.
I think it is the same because x is just an alias for the pointer variable, there is no difference when referring to its address or alias (x).
x
is a pointer variable which contains the address of y
, meaning that the value of x
is equal to the value of &y
.
Upvotes: 1