cpointersformat-specifiers

Pointers in C : Why printf %d for a pointer will show different values at each run, while %p work as expected and show the same address?


I'm trying to understand how C is handling the conversion between a pointer and its address. Some courses online (openclassrooms) suggests that displaying a pointer with %d will just convert the hex to decimal format.

But trying to verify it, that's not the behaviour that i'm seeing.

At each run, the %p will display the same address, but with %d this value is different.

Would someone have an idea why ?

This is my code :

#include <stdio.h>
#include <stdlib.h>

int main (int arg, char *argv[]){

    int age = 10; // variable age
    int *ptrToAge = &age; // pointer (has the '*') that records the RAMemory address of the variable age

    printf("The 'age' variable has a value of %d (%d),\nand its address in RAMemory is %p (%p) [Displayed as d : %d - %d] \n", age, *ptrToAge, &age, (void*)ptrToAge, &age, (void*)ptrToAge);

    return 0;
}

and this are my outputs :

Run n

The 'age' variable has a value of 10 (10),
and its address in RAMemory is 0x16d12716c (0x16d12716c) [Displayed as d : 1829925228 - 1829925228] 

Run n+1

The 'age' variable has a value of 10 (10),
and its address in RAMemory is 0x16d6d716c (0x16d6d716c) [Displayed as d : 1835889004 - 1835889004] 

Of course I have the expected following warnings :

main.c:10:167: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("The 'age' variable has a value of %d (%d),\nand its address in RAMemory is %p (%p) [Displayed as d : %d - %d] \n", age, *ptrToAge, &age, (void*)ptrToAge, &age, (void*)ptrToAge);
                                                                                                                 ~~                                                   ^~~~
main.c:10:173: warning: format specifies type 'int' but the argument has type 'void *' [-Wformat]
    printf("The 'age' variable has a value of %d (%d),\nand its address in RAMemory is %p (%p) [Displayed as d : %d - %d] \n", age, *ptrToAge, &age, (void*)ptrToAge, &age, (void*)ptrToAge);
                                                                                                                      ~~                                                    ^~~~~~~~~~~~~~~

Solution

  • Your observations are incorrect. The %p outputs are not the same; they vary. 0x16d12716c and 0x16d6d716c are different.

    The addresses change from run to run because the program loader randomizes the memory layout to make exploiting program bugs harder. This is called Address Space Layout Randomization (ASLR). The high bits of the layout are the same because the overall layout uses set regions. Some middle bits are set randomly. The low bits remain the same because ASLR uses memory page units, for alignment and memory mapping purposes.

    Although not defined by the C standard, a common behavior of using %d for an address is to produce the address (or part of it) in decimal. When the middle digits of a hexadecimal numeral change, thw low digits of its decimal representation may change.