cpointersmemory-address

Why is the address of the variable changing here?


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?


Solution

  • 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.