0

I'm working with C++ pointers and I've encountered something curious. If I reset a pointer to itself using "b = (int*)&b;", I expected the deferenced output to be the memory address of itself -- since it was pointing to itself.

So I thought *b would be "0x7ffea00819b0", but it's some strange numeric value.

But this isn't the case. The alternate value I get is confusing.

Here is my output:

Value of a = 10
Address of a = 0x7ffea00819ac

Value of b = 0x7ffea00819b0
Address of b = 0x7ffea00819b0
Dereference of b = -1610081872


#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    int a = 10;

    int *b = &a;

    b = (int*)&b;

    cout << "Value of a = " << a << endl;
    cout << "Address of a = " << &a << endl << endl;

    cout << "Value of b = " << b << endl;
    cout << "Address of b = " << &b << endl;
    cout << "Dereference of b = " << *b << endl;
}
Gary
  • 909
  • 9
  • 26
  • 6
    It looks like both `b` and `&b` are printing as `0x7fff5bf19cc8`. All these casts from pointers to non-pointers and pointers to different kinds of pointers don't seem particularly safe, but... What exactly is the behavior that you're expecting to see that you're not seeing? – Nathan Pierson Apr 10 '21 at 18:43
  • `pow` parameters are `double`, and the result is `double`. The unnecessary round trip to a double and back to an unsigned long could cause some funny numbers. An easier way is just to static_cast the address to std::uintptr_t and then output that as decimal. – Eljay Apr 10 '21 at 18:44
  • have you seen [this question](https://stackoverflow.com/questions/28522618/what-does-int-var-mean/28522652)? – ma1169 Apr 10 '21 at 18:46
  • Maybe you can also break down your code to show _only_ the parts you want to ask about or clarify what part of the code you are having trouble with. There are many lines that don't seem to be related to your question and just add noise. – Lukas-T Apr 10 '21 at 18:48
  • I think the confusion probably stems from thinking that `&b` points to `a`. It does not; it points to the pointer that points to `a`. – Mikael Öhman Apr 10 '21 at 18:50
  • I made changes to add some clarity -- apologies, it was indeed confusing at the outset. – Gary Apr 10 '21 at 18:57
  • I'm just trying to further understand pointers in C++. If the value stored at the memory address assigned to b is itself, I would think that a dereference would look at itself for its value. So *b would in effect be b... ? – Gary Apr 10 '21 at 18:59
  • 4
    @Gary dereferencing `b` is UB because at this point `b = (int*)&b;` the code lies to the compiler. `&b` is a `int **` not a `int *`. – Richard Critten Apr 10 '21 at 19:02
  • 2
    If we ignore the UB, the other problem is that the size of `int` might be different from the size of a pointer. Use `std::uintptr_t` instead of `int`. – HolyBlackCat Apr 10 '21 at 19:04
  • Add this to your code after b is defined: `static_assert(sizeof b == sizeof *b);` If that trips, you've got issues. – Eljay Apr 10 '21 at 19:04
  • Thank you Eljay, that was indeed the issue. I changed the type to unsigned long int and they match as expected! Thank you much! – Gary Apr 10 '21 at 19:17
  • Do not use `unsinged long`, use `std::uintptr_t`. On some platforms (on Windows, IIRC) the size of long is different from the size of pointer, which is exactly why we have `std::uintptr_t`. – HolyBlackCat Apr 10 '21 at 19:18
  • Ok, I wasn't aware of this... I'll def. check out and use. Thank you all for such great help! – Gary Apr 10 '21 at 19:21
  • In addition to UB and size/overflow issues, alignment issues may come into play (generally speaking). Some sections of C++17 (draft) relevant to this question: § 6.7.4.3 (3) integer representation of safely-derived pointers, § 6.7.4.3 (4) relaxed & strict pointer safety, § 6.9.2 (3) object pointer type, (4) pointer-interconvertibility, § 6.11 Alignment, § 7.11 Pointer conversions. – outis Apr 26 '21 at 23:58
  • Links to relevant sections in current c++draft: §6.7.5.5.4 [basic.stc.dynamic.safety] [(3) integer representation of safely-derived pointers](http://eel.is/c++draft/basic.memobj#basic.stc.dynamic.safety-3), [(4) relaxed & strict pointer safety](http://eel.is/c++draft/basic.memobj#basic.stc.dynamic.safety-4); § 6.9.2 [basic.compound] [(3) object pointer type](http://eel.is/c++draft/basic.compound#3), [(4) pointer-interconvertibility](http://eel.is/c++draft/basic.compound#4); … – outis Apr 27 '21 at 00:11
  • … § 6.7.76 [basic.align] [Alignment](http://eel.is/c++draft/basic.align), § 7.3.12 [conv.ptr] [Pointer conversions](http://eel.is/c++draft/conv#ptr). – outis Apr 27 '21 at 00:11
  • ... § 6.8.2 [basic.fundamental] [Fundamental types](http://eel.is/c++draft/basic.fundamental) – outis Apr 27 '21 at 00:19

1 Answers1

1

Changing the type to unsigned long int fixed the issue. Thank you all!

#include <iostream>
#include <type_traits>
using namespace std;
        
    int main(int argc, char** argv)
    {
        unsigned long int a = 10;
    
        unsigned long int *b = &a;
    
        b = (unsigned long int*)&b;
    
        cout << "Value of a = " << a << endl;
        cout << "Address of a = " << &a << endl << endl;
    
        cout << sizeof b << endl;
        cout << sizeof *b << endl;
    
        //static_assert(sizeof b == sizeof *b);
    
        cout << "Value of b = " << b << endl;
        cout << "Address of b = " << &b << endl;
        cout << "Dereference of b = " << hex << "0x" << *b << endl;
    }
Gary
  • 909
  • 9
  • 26