Understanding Stack and Heap Addresses in C Programs
As you have spotted, with %p it works as expected.
The explanation at the source of your situation is that %x reads integers (whose size is 4 bytes) out from pointers (whose size is 8 bytes on your architecture).
So, you are simply asking printf to read the first 4 bytes of the pointer, neglecting the rest 4. You may change your format to “0x%016lx” to format pointers with leading zeros.
In those cases where the pointer is small enough to fit in 4 bytes, you see them (haphazardly) correctly because the least significant bytes are stored as first due to the fact that your architecture is little-endian.