3

Is appending '0' as flag to printf %p format specifier correct or not?

#include <stdio.h>
int main()
{
    int a = 42;
    void* p = &a;
    printf("Pointer address: %08p", p);
    return 0;
}

Also on Ideone.

Compiling some code similar to the above, I got no warning or whatsoever from Microsoft Visual C++ 2015, but a warning from GCC 5.4.0:

"warning: '0' flag used with '%p' gnu_printf format [-Wformat]"

Reading from cppreference printf, I see that:

0 : for integer and floating point number conversions, leading zeros are used to pad the field instead of space characters. For integer numbers it is ignored if the precision is explicitly specified. For other conversions using this flag results in undefined behavior. It is ignored if - flag is present.

As far as I can interpret, %p is for pointer address, which is an integer number after all, so does this undefined behavior apply to %p?
If not, why the GCC -Wformat warning?

roalz
  • 2,699
  • 3
  • 25
  • 42
  • I would guess because the code is nonsense that won't compile for fundamental syntax reasons? `printf("Pointer address: %08p", return 0;` Don't type code here, instead copy/paste the actual code or a working example. – Lundin Feb 23 '17 at 13:31
  • Jez, right, I just discovered that copy&paste from Ideone does not work as I expected, edited. – roalz Feb 23 '17 at 13:37

2 Answers2

4

%p is for pointer address, which is an integer number after all,

Nope, a pointer is not an integer from the C/C++ type system point of view.

Pointers are neither arithmetic nor integral types, to be pedantic, see std::is_integral, std::is_arithmetic.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
4

%p is for pointer address, which is an integer number after all

Although pointers do have numeric representation, the standard does not consider pointers an integral data type. Therefore, using %08p format causes undefined behavior.

You can work around this problem by using uintptr_t data type, converting your pointer to it, and then printing it as an unsigned integer:

#include <cinttypes>
#include <cstdint>

int main() {
    int i = 123;
    void* p = &i;
    printf("%08" PRIxPTR "\n", (uintptr_t)p);
    return 0;
}

Demo.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523