In C, I\'d like to use printf to display pointers, and so that they line up properly, I\'d like to pad them with 0s.
My guess was that the proper way to do this was:
The only portable way to print pointer values is to use the "%p"
specifier, which produces implementation-defined output. (Converting to uintptr_t
and using PRIxPTR
is likely to work, but (a) uintptr_t
was introduced in C99, so some compilers may not support it, and (b) it's not guaranteed to exist even in C99 (there might not be an integer type big enough to hold all possible pointer values.
So use "%p"
with sprintf()
(or snprintf()
, if you have it) to print to a string, and then print the string padding with leading blanks.
One problem is that there's no really good way to determine the maximum length of the string produced by "%p"
.
This is admittedly inconvenient (though of course you can wrap it in a function). If you don't need 100% portability, I've never used a system were casting the pointer to unsigned long
and printing the result using "0x%16lx"
wouldn't work. [UPDATE: Yes, I have. 64-bit Windows has 64-bit pointers and 32-bit unsigned long
.] (Or you can use "0x%*lx"
and compute the width, probably something like sizeof (void*) * 2
. If you're really paranoid, you can account for systems where CHAR_BIT > 8
, so you'll get more than 2 hex digits per byte.)
I usually use %x to display pointers. I suppose that isn't portable to 64-bit systems, but it works fine for 32-bitters.
I'll be interested in seeing what answers there are for portable solutions, since pointer representation isn't exactly portable.
Maybe this will be interesting (from a 32-bit windows machine, using mingw):
rjeq@RJEQXPD /u
$ cat test.c
#include <stdio.h>
int main()
{
char c;
printf("p: %016p\n", &c);
printf("x: %016llx\n", (unsigned long long) (unsigned long) &c);
return 0;
}
rjeq@RJEQXPD /u
$ gcc -Wall -o test test.c
test.c: In function `main':
test.c:7: warning: `0' flag used with `%p' printf format
rjeq@RJEQXPD /u
$ ./test.exe
p: 0022FF77
x: 000000000022ff77
As you can see, the %p version pads with zeros to the size of a pointer, and then spaces to the specified size, whereas using %x and casts (the casts and format specifier are highly unportable) uses only zeros.