Today, certainly one of the less sexy thing i’ve ever posted…

How to create a unique key out of two pointers in C++?

After some investigation and a poor attempt to use boost uint128_t, i found my way using a char array.

Here is the code:

SomeClass* a = new SomeClass();
SomeClass* b = new SomeClass();

unique = new unsigned char[ 16 ]; // room for 64bits pointers
uintptr_t ta = reinterpret_cast<uintptr_t>(a);
uintptr_t tb = reinterpret_cast<uintptr_t>(b);

for ( int i = 0; i < 8; ++i ) {
    unique[ i + 8 ] = ta;
    unique[ i ] = tb;
    ta = ta >> 8;
    tb = tb >> 8;
}

cout << "chars: ";
for ( int i = 0; i < 16; ++i ) {
    cout << uint16_t( unique[i] ) << " | ";
}
cout << endl;

uintptr_t newa = 
        unique[15] << 56 | 
        unique[14] << 48 | 
        unique[13] << 40 |
        unique[12] << 32 |
        unique[11] << 24 |
        unique[10] << 16 |
        unique[9] << 8 |
        unique[8];

uintptr_t newb = 
        unique[7] << 56 | 
        unique[6] << 48 | 
        unique[5] << 40 |
        unique[4] << 32 |
        unique[3] << 24 |
        unique[2] << 16 |
        unique[1] << 8 |
        unique[0];

cout << reinterpret_cast<uintptr_t>(a) << " <> " << newa << endl;
cout << reinterpret_cast<uintptr_t>(b) << " <> " << newb << endl;
cout << reinterpret_cast<RoadDot*>(newa) << " <> " << a << endl;
cout << reinterpret_cast<RoadDot*>(newb) << " <> " << b << endl;

And… done! The pointers are casted into the very useful uintptr_t as a unsigned int, stored in the array in 8 bits chunks. On 64 bits systems, pointers use 64bits… Therefore, the char array needs to have 16 slots ( 128 / 8 = 16 ).

At the end of the code, the pointers are recreated from the characters and compared to the original values. In my terminal, here is what i saw:

chars: 96 | 168 | 98 | 1 | 0 | 0 | 0 | 0 | 224 | 130 | 98 | 1 | 0 | 0 | 0 | 0 | 
23233248 <> 23233248
23242848 <> 23242848
0x16282e0 <> 0x16282e0
0x162a860 <> 0x162a860

I’ll optimise this a bit, mainly by creating the char array based on the size of the uintptr_t * 2.