# c – printf() formatting for hexadecimal

## c – printf() formatting for hexadecimal

The `#` part gives you a `0x` in the output string. The `0` and the `x` count against your 8 characters listed in the `08` part. You need to ask for 10 characters if you want it to be the same.

``````int i = 7;

printf(%#010xn, i);  // gives 0x00000007
printf(0x%08xn, i);  // gives 0x00000007
printf(%#08xn, i);   // gives 0x000007
``````

Also changing the case of `x`, affects the casing of the outputted characters.

``````printf(%04x, 4779); // gives 12ab
printf(%04X, 4779); // gives 12AB
``````

The 0x counts towards the eight character count. You need `%#010x`.

Note that `#` does not append the 0x to 0 – the result will be `0000000000` – so you probably actually should just use `0x%08x` anyway.

#### c – printf() formatting for hexadecimal

The `%#08X` conversion must precede the value with `0X`; that is required by the standard. Theres no evidence in the standard that the `#` should alter the behaviour of the `08` part of the specification except that the `0X` prefix is counted as part of the length (so you might want/need to use `%#010X`. If, like me, you like your hex presented as `0x1234CDEF`, then you have to use `0x%08X` to achieve the desired result. You could use `%#.8X` and that should also insert the leading zeroes.

Try variations on the following code:

``````#include <stdio.h>

int main(void)
{
int j = 0;
printf(0x%.8X = %#08X = %#.8X = %#010xn, j, j, j, j);
for (int i = 0; i < 8; i++)
{
j = (j << 4) | (i + 6);
printf(0x%.8X = %#08X = %#.8X = %#010xn, j, j, j, j);
}
return(0);
}
``````

On an RHEL 5 machine, and also on Mac OS X v10.7.5 (Lion), the output was:

``````0x00000000 = 00000000 = 00000000 = 0000000000
0x00000006 = 0X000006 = 0X00000006 = 0x00000006
0x00000067 = 0X000067 = 0X00000067 = 0x00000067
0x00000678 = 0X000678 = 0X00000678 = 0x00000678
0x00006789 = 0X006789 = 0X00006789 = 0x00006789
0x0006789A = 0X06789A = 0X0006789A = 0x0006789a
0x006789AB = 0X6789AB = 0X006789AB = 0x006789ab
0x06789ABC = 0X6789ABC = 0X06789ABC = 0x06789abc
0x6789ABCD = 0X6789ABCD = 0X6789ABCD = 0x6789abcd
``````

Im a little surprised at the treatment of 0; Im not clear why the `0X` prefix is omitted, but with two separate systems doing it, it must be standard. It confirms my prejudices against the `#` option.

The treatment of zero is according to the standard.

### ISO/IEC 9899:2011 §7.21.6.1 The `fprintf` function

¶6 The flag characters and their meanings are:

`#` The result is converted to an alternative form. … For `x` (or `X`)
conversion, a nonzero result has `0x` (or `0X`) prefixed to it. …

Note that using `%#X` will use upper-case letters for the hex digits and `0X` as the prefix; using `%#x` will use lower-case letters for the hex digits and `0x` as the prefix. If you prefer `0x` as the prefix and upper-case letters, you have to code the `0x` separately: `0x%X`. Other format modifiers can be added as needed, of course.

For printing addresses, use the `<inttypes.h>` header and the `uintptr_t` type and the `PRIXPTR` format macro:

``````#include <inttypes.h>
#include <stdio.h>

int main(void)
{
``````Address 0x7FFEE5B29428
Choose your poison on the length — I find that a precision of 12 works well for addresses on a Mac running macOS. Combined with the `.` to specify the minimum precision (digits), it formats addresses reliably. If you set the precision to 16, the extra 4 digits are always 0 in my experience on the Mac, but theres certainly a case to be made for using 16 instead of 12 in portable 64-bit code (but youd use 8 for 32-bit code).