2

I am trying to learn how to display the pointer value in decimal and hexadecimal. below you can see me create a value and try to use a pointer to print out the value and the values location.

Please make the code work correctly so that it prints out the values in decimal and hexadecimal

double val= 1;
printf("The value of val : %f\n",val);


double *ptr;
ptr= &val;

printf("dereference *ptr= %f\n", *ptr);

//Display the location of val with and without pointer use in decimal and hex


//decimal
printf("location of val in decimal with ptr is: %p\n",(void *) ptr); 
printf("location of val in decimal without a pointer is: %p\n",(void *) &val ); 

//hexadecimal THIS IS NOT WORKING 
printf("location of val in hex with ptr is: %#x\n", (void *) ptr); 
printf("location of val in hex without a pointer is: %#x\n", (void *) &val ); 
Barry DeYoung
  • 43
  • 1
  • 6

4 Answers4

5

The %p format takes a void * and prints it in an implementation-defined format. If you want to seize control, use the types from <stdint.h> and formats from <inttypes.h> (first defined in C99):

#include <inttypes.h>

printf("Location in decimal:  %" PRIuPTR "\n", (uintptr_t)ptr);
printf("Location in hex:      0x%.8" PRIXPTR "\n", (uintptr_t)ptr);
printf("Location in octal     %#" PRIoPTR "\n", (uintptr_t)ptr);

Etc.

The uintptr_t type (which is nominally optional, but all practical implementations should define it) is an unsigned integer type big enough to hold a pointer to an object (variable; not necessarily big enough to hold a function pointer). The names such as PRIuPTR define the right conversion specifier for the uintptr_t type (the value is platform specific).

Note that if you use <inttypes.h>, you don't need to include <stdint.h>.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

C usually returns memory addresses as hexadecimal numbers, so you only need to use %p. As for the decimal representation, you can use type casting:

int rand1 = 12, rand2 = 15;

printf("rand1 = %p : rand2 = %p\n\n", &rand1, &rand2); 
// returns hexadecimal value of address

printf("rand1 = %d : rand2 = %d\n\n", (int) &rand1, (int) &rand2);  
// returns decimal value of address
0

Don't forget to include #include <inttypes.h>.

As suggested by the comments, it's better to do this:

//hexadecimal
printf("Location in hex:      0x%.8" PRIXPTR "\n", (uintptr_t)ptr);
printf("Location in hex:      0x%.8" PRIXPTR "\n", (uintptr_t)&val);

If you feel uncomfortable with the unitptr_t cast, then imagine you are casting to an unsigned int. It's not the same, but it's something for a start.

For more, read this answer.

Also, you might want to take a look into the difference between %p and %x.

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • You're correct using `(uintptr_t)` casts. You're incorrect not using `PRIxPTR` etc. Specifically, on a 64-bit Unix system, `%x` is for printing 32-bit (unsigned) integers, but `uintptr_t` is a 64-bit unsigned integer. – Jonathan Leffler Sep 26 '14 at 00:30
  • I see Jonathan, thanks for the advice. Happy to learn new things, here is my +1. – gsamaras Sep 26 '14 at 00:36
  • 1
    Note that the `__STDC_FORMAT_MACROS` should not be necessary with a C99 or C11 compiler for standard C. There seems to have been some confusion a few years ago for C++ compilers. The C99 standard (but not the C11 standard) has a footnote 182 which says: _182) C++ implementations should define these macros only when `__STDC_FORMAT_MACROS` is defined before `` is included._ That does not apply to C implementations; the macros in `` should be defined provided you compile with `-std=c99` or `-std=c11` or the moral equivalents. – Jonathan Leffler Sep 26 '14 at 00:59
0

For decimal use %lu (long unsigned) instead %p Also, no need for the (void *) casting with normal printf function

Like this:

//decimal
printf("location of val in decimal with ptr is: %lu\n",ptr); 
printf("location of val in decimal without a pointer is: %lu\n",&val );

You may use the %p instead %x when printing a pointer in hex format. Like this:

//hexadecimal
printf("location of val in hex with ptr is: %#x\n", ptr); 
printf("location of val in hex without a pointer is: %p\n", &val ); 
user3782235
  • 93
  • 1
  • 3
  • Technically, there is a need to cast to `void *` for `%p` as `%p` is for printing `void *`. There are few machines these days where you'd notice a difference, but I learned C on a machine where, when given `int i = 0; int *ip = &i; char *cp = (char *)&i;`, the values in `ip` and `cp` were not the same when converted to `int` (which was big enough to hold an address). Your code would not work correctly on a Win64 platform; there, a pointer is an 8-byte quantity but `%lu` expects a 4-byte unsigned integer. – Jonathan Leffler Sep 26 '14 at 00:49
  • Yes, for 64bit better use %llu instead. However, pointer is pointer and casting is needed when the value is taken away or size is determined. Other than that, should work. – user3782235 Sep 26 '14 at 00:51