I am learning some C and I am testing simple pointer things so that I can comprehend them more. I think I don't get something right. Given the simple code from below:
#include <stdio.h>
void main() {
long n = 1;
long *y = &n;
n = 2;
printf("n: %d\n",&n);
printf("y: %d\n",y);
}
Results are:
n: 6422296
y: 6422296
Which is the position in memory I guess.
If I change the print lines to:
printf("n: %d\n",&n);
printf("y: %d\n",&y);
Results are:
n: 6422300
y: 6422296
I guess n
is stored 4 bytes after y
in memory but don't get why. I am not changing n
in the output and I am leaving the &
in however the output value changes when adding the &
to the y
.
If I leave it like so:
printf("n: %d\n",n);
printf("y: %d\n",&y);
The output is:
n: 2
y: 6422296
This result is one I was expecting.
Why this behaviour? There is something I'm missing.
Don't be rude. I read tutorials and explanations on pointers but nothing explains these for me.
CodePudding user response:
y
gives you the value, which is the address of n
.
&y
gives you the address of y
, regardless of what type y
is.
&
is the address operator. It gives you the address of the variable.*
when used in expressions, is the dereference operator. It gives you the value to which a pointer points. In your example*y
would give you the value ofn
.*
when used in a declaration (e.g. yourlong *y
) specifies that the variable will hold an address/pointer.
To learn and understand C, it helps to read the appropriate sections of the famous C FAQ.
CodePudding user response:
I think your question comes down to "why does the address of n
change when I add a print of the address of y
". The answer to which comes down to the details of how compilers and optimizers work and how they allocate storage for things.
When you declare a variable local to a function like this, the compiler has a lot of freedom for how to deal with it. It may allocate space in the stack frame it creates for the function, or it may keep the variable in a register, or it may do both, or it may even do something else. The only requirement is that it ends up producing code that matches the execution semantics of the program.
In case of local variables like this, if they never have their address taken (as is the case with y
), then a good compiler will usually try to keep the variable in a register and never allocate memory for it. So in the first program it only needs space for one variable (n
) in the stack frame (n
has its address taken so must reside in memory to have an address).
In the second program, both y
and n
have their addresses taken, so both must be in memory. It so happens that the compiler decides to place y
at the lower address and n
at a larger address, but there is no guarentee of that. There's also no requirement that they be "next to" each other in any sense.
CodePudding user response:
Results re: n: 6422296 y: 6422296 Which is the position in memory I guess.
This makes perfect sense, since your are printing the memory address of n
.
If I change the print lines to:
printf("n: %d\n",&n); printf("y: %d\n",&y);
Results are: n: 6422300 y: 6422296
I guess n is stored 4 bytes after y in memory but don't get why
Yes, and that's how variables are stored in in the stack. The stack grows "backwards" and that's why n
is in a greater memory address than y
.
Remember, you are still printing memory addresses!
If I leave it like so:
printf("n: %d\n",n); printf("y: %d\n",&y);
The output is: n: 2 y: 6422296 This result is one I was expecting.
And this is also perfectly valid, you are printing the value of n
and the memory address of y
.
Note: Your are using %d
for printing memory addresses. You should use %p
, which is specific for pointers or, if you still want to print the integer, %u
for 32 bits and %lu
for 64 bits.
CodePudding user response:
n
is a long, y
is a pointer to long
. Both take up their own memory
I modified your code very slightly:
#include <stdio.h>
void main() {
long n = 1;
long *y = &n;
n = 2;
printf("&n: %p\n",&n); //Please change format specifier to %p for pointer
printf("y: %p\n",y);
}
In the first printf()
call you are printing the address of n
, in the second printf()
call you are printing the value stored in y
. Since you initialized y
with the address of n
, these must be the same.
In your next set of printf()
s (again slightly modified):
printf("n: %ld\n",n); //Please change format specifier to %ld for long int
printf("&y: %p\n",&y); //This one is still a pointer though (long**)
You are printing the value of n
and the address of y
.
The first printf()
must print 2
because it is the most recent value stored in n
. The second printf()
is going to print the address of y
, which is the memory address where the address of n
is stored. &y
is a pointer to a pointer to a long.
printf("&y: %p\n",&y);
can never print the address of n
because y
and n
are stored in different memory locations