I am experimenting with pointers to get a better grip of it and I encountered this situation here: I declared a variable var and two pointers. I was printing var's address to compare it with the two pointers but it kept changing between two values even though the statement was the same?
here is the first time when it gave the address of var to be 0061FF1C
:
the code I used :
#include <stdio.h>
int main () {
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var;
pptr = &ptr;
printf("Address of var = %p\n", &var );
printf("Value available at ptr = %p\n", ptr ); // should be equal to address of Var
printf("Address of ptr = %p\n", &ptr ); // should be equal to address of ptr
printf("value available at pptr = %p\n", pptr); // should be equal to address of ptr
printf("address of pptr = %p\n", &pptr ); // should be equal to address of pptr
return 0;
}
output:
Address of var = 0061FF1C
Value available at ptr = 0061FF1C
Address of ptr = 0061FF18
value available at pptr = 0061FF18
address of pptr = 0061FF14
here is the second time when it gave the address of var to be 0061FF18
:
the code I used :
#include <stdio.h>
int main () {
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var;
pptr = &ptr;
printf("Address of var = %p\n", &var );
printf("Value available at ptr = %p\n", ptr ); // should be equal to address of Var
printf("value available at pptr = %p\n", pptr); // should be equal to address of ptr
return 0;
}
the output:
Address of var = 0061FF18
Value available at ptr = 0061FF18
value available at pptr = 0061FF14
I was expecting the values of var to be the same each time why did it change?
In the program that does not print &pptr
, that object does not need to have an address, so the compiler is able to optimize the program by not actually storing it in memory. The program can hold the value of pptr
in a processor register and/or create it “on the fly” as needed. Since no memory is allocated for it, this changes where other objects, like var
, are located.
Compilers may use complicated algorithms to assign memory to objects. However, in this limited question, we can consider a simplistic view. Essentially, the compiler prepares information about the objects it needs to store on the stack and then assigns locations in the stack frame of main
for those objects, with the result that the first object it assigns a location for will end up at address 0061FF1416, the next at 0061FF1816, and the next at 0061FF1C16. (There are other things in the stack frame, which is why the first object we see in this case starts at 0061FF1416 rather than, say, 0061FF1016.)
In the first version of your program, the program prints the addresses of var
, ptr
, and pptr
. So those objects must have addresses. For whatever reason, the compiler handles them in the order pptr
, ptr
, and var
, giving them the addresses 0061FF1416, 0061FF1816, and 0061FF1C16, respectively.
In the second version of your program, the program prints the addresses of var
and of ptr
(the latter by assigning &ptr
to pptr
and then printing pptr
). It never uses the address of pptr
, so pptr
does not need to have an actual address; the compiler is able to make the program work without ever putting pptr
in memory. So, for this program, the compiler allocates memory for var
and ptr
, and they end up at address 0061FF1416 and 0061FF1816. So the address of ptr
differs by four bytes from the first version of the program.