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.