1

I have:

char* mem = (char*) 0xB8000;

Then mem is passed to a function. Inside the function, I want to get the number 0xB8000 back and compare it to some other integers. How do I convert mem back to the original integer?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Lucy Gu
  • 369
  • 1
  • 3
  • 10

2 Answers2

3

To convert any pointer to an integer, do the following:

#include <stdint.h>

uintptr_t ptr_to_integer(const void *ptr) {
    return (uintptr_t) ptr;
}

Note that the size of uintptr_t might vary between platforms. Also this is an optional part of the C standard, so technically only uintmax_t would be absolutely portable.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
  • It may be worth noting that `uintptr_t` is an optional feature of the ISO C standard, so it may not work on certain compilers. – Andreas Wenzel Aug 18 '20 at 21:51
  • @AndreasWenzel you're right. But you would be hard-pressed trying to find a compiler that doesn't provide this type or other optional typedefs like `uint32_t`. – Jan Schultke Aug 18 '20 at 21:54
  • 1
    Advanced concern: "only unsigned long long would be absolutely portable" --> not quite. 1) `uintmax_t` would be a better choice 2) Both `unsigned long long` and `uintmax_t` are not _specified_ to be wide enough to roundtrip a pointer - yet _practically_ are . The simply advantage to `uintptr_t` is that if code failed to compile due to its absence, it is certain that other integer types will also fail to faithfully round-trip. – chux - Reinstate Monica Aug 19 '20 at 19:30
2

How do I convert mem back to the original integer?

Usually a cast to (u)intptr_t will form the original integer.

include <stdint.h>

printf("o: %lX\n", 0xB8000LU);
char* mem = (char*) 0xB8000;
printf("mem %p\n", (void *) mem);
uintptr_t i =  (uintptr_t) mem;
printf("i: %jX\n", (uintmax_t) i);

Pitfalls

Round tripping (u)intptr_t to void * to uintptr_t (or any integer type) is not specified by C to result in the original value. Even void * to (u)intptr_t to void * is only specified to return an equavalent pointer, not necessarily the same pointer bit pattern.

Casting an arbitrary number like (char*) 0xB8000 to a pointer is not specified to work.

"the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation" C17dr 6.3.2.3 5

(u)intptr_t are optional types - though common. A compliant library may not be able to provide the type.

No corresponding print specifier for (u)intptr_t. A reasonable work-around is to to covert to the widest available type and print.


I want to get the number 0xB8000 back and compare it to some other integers.

A better approach could covert the "other integers" to a char * and compare pointers.

Best for OP to post the larger code usage to handle the overall goal.

Proceed with caution.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256