The C standard does not define a way to calculate the distance between two objects that are not in an array together. C 2018 6.5.6 9 says:
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements…
Paragraph 7 says:
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
Since &first_local_int
and &second_local_int
are not elements in the same array object, the “shall” constraint is violated, and that means the behavior is not defined by the C standard, per 4. 2:
If a "shall" or "shall not" requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined…
Furthermore, if there were a way to calculate the distance between them (such as by using a compiler extension), we cannot expect the distance to be four bytes or one int
. The compiler is free to locate first_local_int
and second_local_int
in memory as it desires. Although it is common for compilers to put such objects near each other, various factors may interfere:
- While the compiler is processing the source code, it might manage declarations in internal data structures in the order it sees them, in alphabetical order, in a hash table, or in any other data structure the compiler author chooses. When memory locations are later assigned to the objects, the compiler may assign them in an order they happen to be in such data structures or other orders.
- The compiler may choose to keep other things in the same memory, including things without names such as temporary variables it creates to assist in evaluating expressions. These items may end up between the named objects.
- Compilers typically arrange objects in memory sorted partially by alignment requirements, to reducing padding or wasted space. While this will not force a rearrangement of objects of identical types, it adds to the general churn of assigning memory.
There is one hope for calculating the distance between two objects. If they are adjacent, first_local_int+1
can compare equal to second_local_int
or vice-versa, because 6.5.9 6 and 7 say:
Two pointers compare equal if and only if … both are pointers to the same object … or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
Thus, the behaviors of first_local_int+1 == second_local_int
and second_local_int+1 == first_local_int
are defined by the C standard, and, if either evaluates as true, one may conclude they are adjacent in memory. If both are false, one may conclude they are not adjacent, but the distance between them is otherwise unknown.