74

After all, both these statements do the same thing...

int a = 10;
int *b = &a;
printf("%p\n",b);
printf("%08X\n",b);

For example (with different addresses):

0012FEE0
0012FEE0

It is trivial to format the pointer as desired with %x, so is there some good use of the %p option?

Synetech
  • 9,643
  • 9
  • 64
  • 96
Moeb
  • 10,527
  • 31
  • 84
  • 110
  • 2
    By using '%p' you print the address of the variable in question, "The void * pointer argument is printed in hexadecimal (as if by %#x or %#lx)." –  Mar 03 '10 at 10:26
  • In C++, you can use (void *) typecast: see http://stackoverflow.com/questions/5657123/how-to-simulate-printfs-p-format-when-using-stdcout – kagali-san Apr 14 '11 at 00:21

7 Answers7

148

They do not do the same thing. The latter printf statement interprets b as an unsigned int, which is wrong, as b is a pointer.

Pointers and unsigned ints are not always the same size, so these are not interchangeable. When they aren't the same size (an increasingly common case, as 64-bit CPUs and operating systems become more common), %x will only print half of the address. On a Mac (and probably some other systems), that will ruin the address; the output will be wrong.

Always use %p for pointers.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • 16
    %p will also use an adequate textural representation for pointer for the platform. On platforms where it is common to represent pointer in hex, this won't make a difference as long as the size is correct but for a segmented architecture (do you remember DOS?) it may use a segment:offset representation. – AProgrammer Mar 03 '10 at 08:23
  • 12
    One also needs to cast `b` to `void *` with the `%p` format - this is one of the few instances in C where one needs a cast. – Alok Singhal Mar 03 '10 at 11:25
  • 1
    "All the world's a VAX!" syndrome. – David Cary Aug 22 '11 at 20:30
  • Adding to @AlokSinghal comment: for GCC if you compile with the ```-Wextra``` flag you will get appropriate warnings for incorrect types in ```printf```. To make the warning go away you need to use the correct form and cast to ```void*``` which can be helpful. – Fred Jul 23 '18 at 22:35
9

At least on one system that is not very uncommon, they do not print the same:

~/src> uname -m
i686
~/src> gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
[some output snipped]
gcc version 4.1.2 (Gentoo 4.1.2)
~/src> gcc -o printfptr printfptr.c
~/src> ./printfptr
0xbf8ce99c
bf8ce99c

Notice how the pointer version adds a 0x prefix, for instance. Always use %p since it knows about the size of pointers, and how to best represent them as text.

unwind
  • 391,730
  • 64
  • 469
  • 606
5

You cannot depend on %p displaying a 0x prefix. On Visual C++, it does not. Use %#p to be portable.

Ajay
  • 18,086
  • 12
  • 59
  • 105
Mauritius
  • 51
  • 1
  • 1
  • 1
    Is this documented somewhere? I cannot find anything about # used in conjunction with %p. I have checked: http://msdn.microsoft.com/en-us/library/8aky45ct(v=vs.71).aspx http://www.cplusplus.com/reference/clibrary/cstdio/printf/ – Suma Sep 25 '12 at 10:24
  • 1
    PC-Lint doesn't like it, but it works in Visual Studio. Unfortunately it prepends '0X' not '0x', making the actual value hard to read. Presumably this is due to a missing '%P' variant. All told, this format specifier suffers from the problem of all 'platform dependent' implementations, that you can't really control what you're going to get. I use '0x%p' at the risk of getting a double 0x0X at the start. Rather undermines using it, because you know exactly what you're getting with %x. – Andy Krouwel Jan 09 '15 at 10:32
  • This doesn't seem to be at all portable, even between VC versions. For example, VS 2013 (12.0.40629.00 update 5) prefixes '0X' for "%#p" but has no prefix for "%p". But VC 19.00.23506 doesn't prefix for either "%p" or "%#p". Then G++ 5.4.0 prefixes with "0x" for both "%p" and "%#p" (and using "%#p" gives a G++ warning). In short, you can't rely on the format of this at all. – james Feb 21 '19 at 11:38
5

The size of the pointer may be something different than that of int. Also an implementation could produce better than simple hex value representation of the address when you use %p.

Ajay
  • 18,086
  • 12
  • 59
  • 105
Tronic
  • 10,250
  • 2
  • 41
  • 53
2

x is Unsigned hexadecimal integer ( 32 Bit )

p is Pointer address

See printf on the C++ Reference. Even if both of them would write the same, I would use %p to print a pointer.

Filip Ekberg
  • 36,033
  • 20
  • 126
  • 183
  • yeah, I already went through that page. What I wanted to know was why would you `use %p to print a pointer`. Anyways, Peter Hosey's answer answers my doubt. – Moeb Mar 03 '10 at 08:06
2

When you need to debug, use printf with %p option is really helpful. You see 0x0 when you have a NULL value.

albttx
  • 3,444
  • 4
  • 23
  • 42
  • 1
    On gcc (4.4.7, at least), a NULL value shows as `(nil)` -- including the parentheses. There seems to be a lot of implementation-specific variation in `%p` – Steve Friedl Jan 07 '19 at 01:26
-2

x is used to print t pointer argument in hexadecimal.

A typical address when printed using %x would look like bfffc6e4 and the sane address printed using %p would be 0xbfffc6e4

codaddict
  • 445,704
  • 82
  • 492
  • 529
  • 1
    No, `%x` is used to print a value of type `unsigned int` in hexadecimal. There's absolutely no guarantee that `unsigned int` is the same size as `void *`, and it's a bad idea to assume so in code. – unwind Oct 05 '14 at 15:51