Search code examples
c++pointersinteger-arithmetic

Why is it not possible to add two addresses together?


Let's say I've defined two variables x and y:

int x = 5;
int y = 6;

I can get the address where x is stored via:

cout << &x << endl; // 0x61fe18

Which is a hexadecimal number. Now, if I want to print this number after adding 5, it is fairly simple:

cout << &x + 5 << endl; // 0x61fe1d

But if I sum together the addresses of x and y:

cout << &x + &y << endl;

I get an error:

invalid operands of types 'int*' and 'int*' to binary 'operator+'
cout << &x + &y << endl;
        ~~~^~~~

Why can't I add the two addresses?


Solution

  • The ability to convert something to an integer does not mean it is an integer.

    Computers use binary logic, and you can take any piece of information in binary and convert it to an integer. But for it to be an integer, it means that addition, subtraction, multiplication and division all have the expected meaning.

    Pointers are stored as binary data, but many operations do not make sense on them.

    My location on the planet Earth can be represented as a pair of lat/long numbers. That pair of numbers is not my location on the planet Earth.

    Adding together numbers is a reasonable operation. Adding together locations is nonsense.

    "Location of NYC" plus "Location of Moscow" does not make sense.

    "Latitude of NYC" plus "Latitude of Moscow" is a number, but that number is basically nonsense, and the pair of Lat/Long values of the sum of the Lat/Long values of NYC and Moscow equally so.

    The midpoint between NYC and Moscow does make sense, but there are two of them (opposite sides of the world). Also, 25% of the way between NYC and Moscow makes sense.

    Next "the shortest way to get from NYC to Moscow" is a vector. It isn't a location, but a direction on the surface of the Earth. You can take that vector and add it to another location -- "what if I started in Toronto instead" -- and get a new location.

    Pointers are locations, like "NYC" and "Moscow". When you add to a pointer, that integer is acting as a vector on the space of pointer locations.

    C++ attempts to make nonsense operations not happen unless you force it. Adding pointers -- adding locations -- is nonsense. Adding an integer to a pointer makes sense. Taking the difference between two pointers makes sense.

    When you print out a pointer, the compiler uses the void* overload of std::ostream& << void*. This overload is provided for debugging purposes, and interprets the bits of the pointer as a hexidecimal integer.

    You can do this manually by converting your pointer to a std::uintptr_t -- an unsigned integer type guaranteed to be large enough to store the bits of a pointer.


    You'll note that when you do &x + 5, the integer you get isn't 5 greater than if you do &x. In fact, it is &x + sizeof(x)*5.

    This is because pointer arithmetic is assuming you are working on an array, and is moving forward/backwards by one object-size.

    std::cout << &x << std::endl; // 0x61fe18
    std::cout << (&x + 5) << std::endl; // 0x61fe1d
    

    that only happens if x has sizeof(x)==1. As you claimed x was an int, that is not possible in C++.

    If sizeof(int) is 4 (as is common nowadays),

    std::cout << &x << std::endl; // 0x61fe18
    std::cout << (&x + 5) << std::endl; // 0x61fe2c
    

    is what you'd get instead.

    And this is because, again, pointers are not integers. The ability to print them as integers does not mean they are integers.