Which format specifier should I be using to print the address of a variable? I am confused between the below lot.
%u - unsigned integer
%x - hexadecimal value
%p - void pointer
Which would be the optimum format to print an address?
Which format specifier should I be using to print the address of a variable? I am confused between the below lot.
%u - unsigned integer
%x - hexadecimal value
%p - void pointer
Which would be the optimum format to print an address?
As an alternative to the other (very good) answers, you could cast to
uintptr_t
orintptr_t
(fromstdint.h
/inttypes.h
) and use the corresponding integer conversion specifiers. This would allow more flexibility in how the pointer is formatted, but strictly speaking an implementation is not required to provide these typedefs.Use
%p
, for "pointer", and don't use anything else*. You aren't guaranteed by the standard that you are allowed to treat a pointer like any particular type of integer, so you'd actually get undefined behaviour with the integral formats. (For instance,%u
expects anunsigned int
, but what ifvoid*
has a different size or alignment requirement thanunsigned int
?)*) [See Jonathan's fine answer!] Alternatively to
%p
, you can use pointer-specific macros from<inttypes.h>
, added in C99.All object pointers are implicitly convertible to
void*
in C, but in order to pass the pointer as a variadic argument, you have to cast it explicitly (since arbitrary object pointers are only convertible, but not identical to void pointers):The simplest answer, assuming you don't mind the vagaries and variations in format between different platforms, is the standard
%p
notation.The C99 standard (ISO/IEC 9899:1999) says in §7.19.6.1 ¶8:
(In C11 — ISO/IEC 9899:2011 — the information is in §7.21.6.1 ¶8.)
On some platforms, that will include a leading
0x
and on others it won't, and the letters could be in lower-case or upper-case, and the C standard doesn't even define that it shall be hexadecimal output though I know of no implementation where it is not.It is somewhat open to debate whether you should explicitly convert the pointers with a
(void *)
cast. It is being explicit, which is usually good (so it is what I do), and the standard says 'the argument shall be a pointer tovoid
'. On most machines, you would get away with omitting an explicit cast. However, it would matter on a machine where the bit representation of achar *
address for a given memory location is different from the 'anything else pointer' address for the same memory location. This would be a word-addressed, instead of byte-addressed, machine. Such machines are not common (probably not available) these days, but the first machine I worked on after university was one such (ICL Perq).If you aren't happy with the implementation-defined behaviour of
%p
, then use C99<inttypes.h>
anduintptr_t
instead:This allows you to fine-tune the representation to suit yourself. I chose to have the hex digits in upper-case so that the number is uniformly the same height and the characteristic dip at the start of
0xA1B2CDEF
appears thus, not like0xa1b2cdef
which dips up and down along the number too. Your choice though, within very broad limits. The(uintptr_t)
cast is unambiguously recommended by GCC when it can read the format string at compile time. I think it is correct to request the cast, though I'm sure there are some who would ignore the warning and get away with it most of the time.Kerrek asks in the comments:
I was under the illusion that the C standard says that all object pointers must be the same size, so
void *
andint *
cannot be different sizes. However, what I think is the relevant section of the C99 standard is not so emphatic (though I don't know of an implementation where what I suggested is true is actually false):(C11 says exactly the same in the section §6.2.5, ¶28, and footnote 48.)
So, all pointers to structures must be the same size as each other, and must share the same alignment requirements, even though the structures the pointers point at may have different alignment requirements. Similarly for unions. Character pointers and void pointers must have the same size and alignment requirements. Pointers to variations on
int
(meaningunsigned int
andsigned int
) must have the same size and alignment requirements as each other; similarly for other types. But the C standard doesn't formally say thatsizeof(int *) == sizeof(void *)
. Oh well, SO is good for making you inspect your assumptions.The C standard definitively does not require function pointers to be the same size as object pointers. That was necessary not to break the different memory models on DOS-like systems. There you could have 16-bit data pointers but 32-bit function pointers, or vice versa. This is why the C standard does not mandate that function pointers can be converted to object pointers and vice versa.
Fortunately (for programmers targetting POSIX), POSIX steps into the breach and does mandate that function pointers and data pointers are the same size:
So, it does seem that explicit casts to
void *
are strongly advisable for maximum reliability in the code when passing a pointer to a variadic function such asprintf()
. On POSIX systems, it is safe to cast a function pointer to a void pointer for printing. On other systems, it is not necessarily safe to do that, nor is it necessarily safe to pass pointers other thanvoid *
without a cast.p
is the conversion specifier to print pointers. Use this.Remember that omitting the cast is undefined behavior and that printing with
p
conversion specifier is done in an implementation-defined manner.