how to printf 0x0000000 instead of (nil) and 0x08ffffff instead of 0x8ffffff in c

2

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?

c
pointers
printf
stdout
asked on Stack Overflow Feb 2, 2021 by Hadi • edited Feb 2, 2021 by Antti Haapala

1 Answer

2

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.

answered on Stack Overflow Feb 2, 2021 by Eric Postpischil • edited Feb 2, 2021 by Eric Postpischil

User contributions licensed under CC BY-SA 3.0