Difference between %p and %x in C/C++

Here we will see what are the differences between %p and %x in C or C++. The %p format specifier is used to print pointer values (memory addresses), while %x is used to print unsigned integers in hexadecimal format. Though pointers can also be displayed using %u or %x, the correct and portable way to print a pointer is %p.

The visible difference is that %p prints with leading zeros and is platform-width aware (16 hex digits on 64-bit systems, 8 on 32-bit), while %x prints only the significant digits without padding.

Syntax

printf("%p", pointer);    // prints address with leading zeros
printf("%x", integer);    // prints integer as hexadecimal (lowercase)
printf("%X", integer);    // prints integer as hexadecimal (uppercase)

Example − Comparing %p and %x

The following example shows how the same value appears differently with %p and %x

#include <stdio.h>

int main() {
   int x = 59;
   printf("Value using %%p: %p\n", (void *)&x);
   printf("Value using %%x: %x\n", x);
   printf("Value using %%X: %X\n", x);
   return 0;
}

The output of the above code is −

Value using %p: 0x7ffd5e8a3c4c
Value using %x: 3b
Value using %X: 3B

Notice that %p prints the full memory address of x with a 0x prefix, while %x prints the value 59 as 3b in hexadecimal without leading zeros. %X prints the same but in uppercase.

Example − Printing Pointer Addresses

The correct use of %p is to print the memory address held by a pointer variable −

#include <stdio.h>

int main() {
   int a = 100;
   int *ptr = &a;

   printf("Value of a: %d\n", a);
   printf("Address using %%p: %p\n", (void *)ptr);
   printf("Address using %%x: %x\n", (unsigned int)(unsigned long)ptr);
   return 0;
}

The output of the above code is −

Value of a: 100
Address using %p: 0x7ffc12ab9d24
Address using %x: 12ab9d24

When using %x to print a pointer, the address may be truncated on 64-bit systems because %x expects an unsigned int (32 bits), while a pointer may be 64 bits. This is why %p is the safe and portable choice for printing addresses.

Key Differences

Feature %p %x
Purpose Print pointer (memory address) Print unsigned int as hexadecimal
Expected argument void * unsigned int
Leading zeros Yes (platform-width padded) No
Prefix Typically 0x (implementation-defined) None (unless %#x is used)
Width Matches pointer size (8 or 16 hex digits) Only significant digits
64-bit safe Yes No (truncates upper 32 bits)
Case Implementation-defined Lowercase (%X for uppercase)

Conclusion

The %p format specifier is designed specifically for printing pointer addresses and is portable across 32-bit and 64-bit systems. The %x specifier prints unsigned integers in hexadecimal and should not be used for pointers, as it may truncate the address on 64-bit platforms. Always use %p with a (void *) cast when printing memory addresses.

Updated on: 2026-03-18T08:01:30+05:30

10K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements