You cannot perform arithmetic on a uintptr_t
in a portable manner. Here's how that type is defined:
7.18.1.4 Integer types capable of holding object pointers
The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
intptr_t
The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:
uintptr_t
These types are optional.
Note that the specification doesn't say anything about how the pointer is represented. On most implementations, arithmetic on uintptr_t
values will probably have the expected result, but if you want your code to be portable, you should use pointer arithmetic, as it has well specified semantics.
An example of a platform where uintptr_t
arithmetic might have unexpected behavior is IBM's z/OS. In legacy 31-bit mode (yes, 31), the most significant pointer bit is reserved for the system. If you have two pointers a
and b
which differ only in that bit, comparing those pointers with a==b
will return 1 (true) as expected, and subtracting them with a-b
will return 0. But if you cast those pointers to uintptr_t
values and compare them, ==
will return 0, and -
will return non-0.