I'm learning the basics of C and I'm confused about the difference between the `%p` and `%x` format specifiers. I understand that `%p` is used to print a pointer address and `%x` prints a value in hexadecimal, but they often seem to produce similar-looking output. Why are both available, when should each one be used, and does using `%x` with a pointer cause any problems?
3 Answers
A pointer can be converted to text that looks like a hexadecimal number, but that does not make it an integer. `%p` expects a `void *`, so other pointer types should be cast when passed to `printf`, for example `printf("%pn", (void *)ptr);`. The address-of operator `&x` obtains the address of `x`; `%p` only controls how that pointer is printed. Printing an address is mostly useful for debugging and learning how memory works.
`%p` is specifically for printing a pointer, while `%x` is for printing an `unsigned int` in hexadecimal. For example: `printf("%pn", (void *)&x);` prints the address of `x`. The `%p` conversion is designed for pointer values and uses the format required by the implementation. `%x` should only be used when the argument is an integer, such as `printf("%xn", value);`. Even if both outputs look like hexadecimal addresses on your computer, they are not interchangeable in standard C.
Exactly. Since `printf` is variadic, it relies on the format string to interpret each argument correctly. Using the wrong specifier can produce undefined behavior, even if it appears to work on one machine.
On many modern systems, an `int` and a pointer happen to be passed in similar ways, which is why `%x` with a pointer may appear to work. That is not guaranteed by the C standard, though. Pointer sizes and representations can differ from integer sizes, and variadic functions do not automatically know the types of their arguments. Use `%p` for pointers and `%x` for unsigned integers to keep the code portable and defined.

So `%p` is mainly about telling `printf` the actual argument type, rather than just choosing how the number looks?