Hexadecimal prefix
There are multiple ways to add the hexadecimal prefix to the output:
#include <stdio.h>
int main(void)
{
printf("Diff = %#x\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = 0x%X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#.8x\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#.8X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = 0x%.8X\n", 0xFFFFFFFF - 0xFF012345);
return 0;
}
The output is:
Diff = 0xfedcba
Diff = 0XFEDCBA
Diff = 0xFEDCBA
Diff = 0x00fedcba
Diff = 0X00FEDCBA
Diff = 0x00FEDCBA
You can choose the 0x
lower-case prefix with the lower-case hex digits, or the upper-case prefix with the upper-case digits. Personally, I like the lower-case prefix and the upper-case digits, so I always use the third option.
The #
flag for printf()
chooses an alternative representation:
#
— Specifies that the value is to be converted to an alternative form. For o
conversion, it shall increase the precision, if and only if necessary, to force the first digit of the result to be a zero (if the value and precision are both 0
, a single 0
is printed). For x
or X
conversion specifiers, a non-zero result shall have 0x
(or 0X
) prefixed to it. For a
, A
, e
, E
, f
, F
, g
, and G
conversion specifiers, the result shall always contain a radix character, even if no digits follow the radix character. Without this flag, a radix character appears in the result of these conversions only if a digit follows it. For g
and G
conversion specifiers, trailing zeros shall not be removed from the result as they normally are. For other conversion specifiers, the behavior is undefined.
Leading zeros
You can specify the number of digits in various ways, not always with the desired result when using the manual prefix. Note that the prefix is counted in the minimum field width when the #
flag is used.
#include <stdio.h>
int main(void)
{
printf("Diff = %#x\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = 0x%X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#.8x\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#.8X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = 0x%.8X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#10x\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#10X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = 0x%10X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#10.10x\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = %#10.10X\n", 0xFFFFFFFF - 0xFF012345);
printf("Diff = 0x%10.10X\n", 0xFFFFFFFF - 0xFF012345);
return 0;
}
Output:
Diff = 0xfedcba
Diff = 0XFEDCBA
Diff = 0xFEDCBA
Diff = 0x00fedcba
Diff = 0X00FEDCBA
Diff = 0x00FEDCBA
Diff = 0xfedcba
Diff = 0XFEDCBA
Diff = 0x FEDCBA
Diff = 0x0000fedcba
Diff = 0X0000FEDCBA
Diff = 0x0000FEDCBA
On 32-bit systems, I normally use 0x%8.8X
; on 64-bit systems, I use one of 0x%12.12X
or 0x%16.16X
. The latter often leaves the addresses I'm printing with more leading zeros than I want.
You can left-justify if you need to, and so on and so forth. See the specification of printf()
already linked, which is formally for POSIX but the POSIX extensions are clearly marked.
And for printing addresses, I use uintptr_t
and PRIXPTR
from <inttypes.h>
, leading to a format string along the lines of:
printf("0x%8.8" PRIXPTR "\n", (uintptr_t)&x);
As you can see, there are many variations that can be used — you need to choose what works best for you.