I've been trying to understand pointers, in particular the pointer[i] notation which is the equivalent of *(pointer + i), ie dereferencing the value at the next address, so if its an int pointer than the next 4 byte address. And I tried running the following code below:
#include <stdio.h>
int main(void){
int x = 10;
int y = 20;
int* z = &y;
printf("address of x: %u ", &x);
printf("address of y: %u", &y);
printf("value at address: %u \n", *(z+1));
}
I noticed that 'y' was stored 4 bytes before 'x', and thought that i would be able to return the value stored at x's address by z[1] or *(z+1), which worked fine.
However when I removed the first 2 printf's, I ended up with the address being outputted instead of the actual value (10), here is the code for this case:
#include <stdio.h>
int main(void){
int x = 10;
int y = 20;
int* z = &y;
printf("value at address: %u \n", *(z+1));
}
I am assuming that *(z+1) is no longer referring to the same area of memory as the variable 'x' , but I am confused as to why this change in the code caused this.
Initially i thought it was one off, so I tried this multiple times and got the same results each time.
Whats even more confusing is how the code works as expected in both cases on ubuntu and macos, but not on windows.
Any help regarding this would be great, thanks.
Here I can only answer part of your question and present my observations.
Here is the code modified.
#include <stdio.h>
int main(void) {
int x = 10;
int y = 20;
int *intp = &y;
// printf("address of x is %p.\n", &x);
// printf("address of y is %p.\n", &y);
printf("*(intp + 1) is %u.\n", *(intp + 1));
printf("*(intp) is %u.\n", *(intp));
printf("*(intp - 1) is %u.\n", *(intp - 1));
printf("difference of addresses: &x - &y = %d.\n", &x - &y);
return 0;
}
I get consistent results for *(intp)
,
*(intp - 1)
and &x - &y
, while
*(intp + 1)
would change. One of the output is
*(intp + 1) is 2028820428.
*(intp) is 20.
*(intp - 1) is 10.
difference of addresses: &x - &y = -1.
However, if I comment out the line using &x
,
// printf("difference of addresses: &x - &y = %d.\n", &x - &y);
the output would be consistent, as follows
*(intp + 1) is 10.
*(intp) is 20.
*(intp - 1) is 0.
My idea is that, on my gcc 10.2.0
on Linux,
&x
is used, x
is
stored at a lower address than y
, by 4 bytes. As
int
is of 4 bytes on my computer, &x - &y
always is -1
.&x
is not used, x
is stored at a higher address than y
, by 4 bytes.So the compiler did set space to store x
and
y
, even when x
is not used. But I
don't know why their positions would differ in the two cases. Compilers
could try to optimize the code, but I have little knowledge of that.
Besides, if you want to try to use gdb
to test the
addresses, you could try
gcc -g thecode.c
gdb a.out
(gdb) break main
(gdb) run
(gdb) p &x
(gdb) p &y
(gdb) p &x + 1
(gdb) step
(gdb) (press enter directly to use the last same command...)
(gdb) quit