For int *a, int *b
, does a == b
imply (intptr_t)a == (intptr_t)b
? I know that it's true for example on a modern X86 CPU, but does the C standard or POSIX or any other standard give a guarantee for this?
A pointer holds a memory address, from 0 to the upper limit of your memory. So in math terms, a pointer could be considered a non-negative integer.
In C language pointers can be compared if the two pointers are pointing to the same array. All relational operators can be used for pointer comparison, but a pointer cannot Multiplied or Divided.
This is not guaranteed by the C standard. (This answer does not address whether POSIX or other standards say about intptr_t
.) What the C standard (2011, draft N1570) says about intptr_t
is:
7.20.1.4 1 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
As a theoretical proof, one counterexample is a system that has 24-bit addresses, where the high eight bits are unused, but the available integer types are 8-bit, 16-bit, and 32-bit. In this case, the C implementation could make intptr_t
a 32-bit integer, and it could convert a pointer to intptr_t
by copying the 24-bit address into the 32-bit integer and neglecting the high eight bits. Those bits might be left over from whatever was lying around previously. When the intptr_t
value is converted back to a pointer, the compiler discards the high eight bits, which results in the original address. In this system, when a == b
is evaluated for pointers a
and b
, the compiler implements this by comparing only the 24 bits of the address. Thus, if a
and b
point to the same object a == b
will be true, but (intptr_t) a == (intptr_t) b
may evaluate to false because of the neglected high bits. (Note that, strictly, a
and b
should be pointers to void
or should be converted to pointers to void
before being converted to intptr_t
.)
Another example would be a system which uses some base and offset addressing. In this system, a pointer might consist of 16 bits that specify some base address and 16 bits that specify an offset. The base might be in multiples of 64 bytes, so the actual address represented by base and offset is base•64 + offset. In this system, if pointer a
has base 2 and offset 10, it represents the same address as pointer b
with base 1 and offset 74. When comparing pointers, the compiler would evaluate base•64 + offset for each pointer and compare the results, so a == b
evaluates to true. However, when converting to intptr_t
, the compiler might simply copy the bits, thus producing 131,082 (2•65536 + 10) for (intptr_t) a
and 65,610 (1•65536 + 74) for (intptr_t) b
. Then (intptr_t) a == (intptr_t) b
evaluates to false. But the rule that converting an intptr_t
back to a pointer type produces the original pointer still holds, as the compiler will simply copy the bits again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With