What's the proper use of printf to display pointers padded with 0s

Viewed 38713

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:

printf("%016p", ptr);

This works, but this gcc complains with the following message:

warning: '0' flag used with ā€˜%p’ gnu_printf format

I've googled a bit for it, and the following thread is on the same topic, but doesn't really give a solution.

http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html

Reading it, it seems that the reason why gcc complains is that the syntax I suggested is not defined in C99. But I can't seem to find any other way to do the same thing in a standard approved way.

So here is the double question:

  • Is my understanding correct that this behavior is not defined by the C99 standard?
  • If so, is there a standard approved, portable way of doing this?
9 Answers

#include <inttypes.h>

#include <stdint.h>

printf("%016" PRIxPTR "\n", (uintptr_t)ptr);

but it won't print the pointer in the implementation defined way (says DEAD:BEEF for 8086 segmented mode).

Use:

#include <inttypes.h>

printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);

Or use another variant of the macros from that header.

Also note that some implementations of printf() print a '0x' in front of the pointer; others do not (and both are correct according to the C standard).

It's easy to solve if you cast the pointer to a long type. The problem is this won't work on all platforms as it assumes a pointer can fit inside a long, and that a pointer can be displayed in 16 characters (64 bits). This is however true on most platforms.

so it would become:

printf("%016lx", (unsigned long) ptr);

As your link suggests already, the behaviour is undefined. I don't think there's a portable way of doing this as %p itself depends on the platform you're working on. You could of course just cast the pointer to an int and display it in hex:

printf("0x%016lx", (unsigned long)ptr);

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.

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.

Related