0

What would be the proper way to find the difference between two memory addresses? For example:

int first_local_int = 44;
int second_local_int = 92;

printf(
        "The first number is %d and located on the stack at: %p.\n"
        "The second number is %d and located on the stack at: %p.\n"
        "The difference between these memory addresses on the stack should be: %d.\n"
        "The actual difference between the two memory addresses is: %d" ,
         first_local_int, &first_local_int,
         second_local_int, &second_local_int,
         sizeof(first_local_int), 
         &second_local_int - &first_local_int // how to do this?
);

Specifically, I mean the proper way to do &second_local_int - &first_local_int, where the answer should be (I think?) and unsigned long, in the above, it should be 4.

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58

1 Answers1

3

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.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • thanks could you please link the `C 2018 6.5.6 9` in the answer? – samuelbrody1249 Oct 31 '20 at 22:06
  • 1
    @samuelbrody1249: The official draft of C 2018 is a copyrighted, paid document and is not publicly available online to my knowledge. C 2018 contains only technical corrections and clarifications from C 2011. A working-committee draft version of C 2011 is [here](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf). Information about the various versions of the C and C++ standards, including where you can purchase official copies, is [here](https://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents). – Eric Postpischil Oct 31 '20 at 22:09
  • thanks, is the 'standard' geared towards compiler engineers or what's the target audience of the people that would be reading something that is so in-depth about all the agreed-upon implementation details? – samuelbrody1249 Oct 31 '20 at 22:11
  • @samuelbrody1249: The C standard is quite readable by moderately experienced software engineers. Students already somewhat proficient with C may find it a bit difficult to understand at first but should be able to benefit from it significantly right away and can grow into it over time. – Eric Postpischil Oct 31 '20 at 22:13