Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does pointer equality imply integer equality?

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?

like image 425
Manuel Jacob Avatar asked Jun 06 '18 17:06

Manuel Jacob


People also ask

Can an integer be a pointer?

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.

Can you compare pointers in C?

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.


1 Answers

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.

like image 118
Eric Postpischil Avatar answered Oct 01 '22 11:10

Eric Postpischil