I am trying to use the stdout stream
to print 0x00000000
instead of (nil)
and 0x08ffffff
instead of 0x8ffffff
.
So basically, char *ptr1 = 0x00000000
and char *ptr2 = 0x08ffffff
.
When I run
printf("start of address is %p and end of address is %p", ptr1, ptr2);
I get
start of address is (nil) and end of address is 0x8ffffff
I actually found a way around this and I would actually do this:
char *ptr1 = 0x00000000;
char *ptr2 = 0x08ffffff;
printf("start 0x%08x and end 0x%08x\n",ptr1, ptr2);
This generates
start 0x00000000 and end 0x08ffffff
However, the compiler sends the following warning:
warning: format ‘%x’ expects argument of type ‘unsigned int’,
but argument 3 has type ‘void *’ [-Wformat=]
How should I modify printf to adjust the output print?
First, to have any control over how addresses are printed, you must convert them to an integer type. The specifications for printing pointers with %p
are inadequate. To do this, you can include <stdint.h>
and use the type uintptr_t
, which is an unsigned integer type suitable for some work with addresses.
Second, the header <inttypes.h>
provides a macro PRIxPTR
that provides a printf
conversion specifier for printing uintptr_t
values in hexadecimal.
Third, you can add a flag 0
and a minimum field width 8
to request the conversion pad with zeros to at least eight digits.
Here is sample code:
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
static void PrintAddress(const void *p)
{
uintptr_t u = (uintptr_t) p;
printf("0x%08" PRIxPTR, u);
}
int main(void)
{
char *ptr1 = (char *) 0x00000000;
char *ptr2 = (char *) 0x08ffffff;
printf("Start of address is ");
PrintAddress(ptr1);
printf(" and end of address is ");
PrintAddress(ptr2);
printf(".\n");
}
Better yet, you can adapt the field width to the size of uintptr_t
in your C implementation by including <limits.h>
and calculating the number of digits needed:
printf("0x%0*" PRIxPTR, ((int) sizeof u * CHAR_BIT + 3) / 4, u);
Note that directly setting pointers to hard-coded constant values, as you do with the initializations of ptr1
and ptr2
, is rare. It is generally used in doing special things with hardware. When you are deliberately converting an integer to a pointer, you should use a cast to avoid a compiler warning.
User contributions licensed under CC BY-SA 3.0