I was reading the source of a hashing competition today, and came across this:
#define BYTES_IN_BLOCK 1024 struct block{ uint8_t v[BYTES_IN_BLOCK]; block(){ memset(v, 0, BYTES_IN_BLOCK); } uint64_t& operator[](uint8_t i){ return *(uint64_t*)(v + 8 * i); } }; Then, a little later in the code, there's this:
state = new block[cost]; // cost is a uint32_t (like 1024) // Probably 50 lines of code. block prev_block; prev_block = state[foo]; // foo is a uint32_t What I can't figure out is what this is doing. Now, I understand C, but C++ not so much. Bear with me here for a second.
This part: return *(uint64_t*)(v+8*i) should return a uint64_t, and does so when I tested it:
state->v[8*10] = 12; uint64_t bar = *(uint64_t*)(v+8*10); printf("%" PRIu64 "\n", bar); So that all makes sense.
But this:
prev_block = state[foo];
Makes no sense. Since state is block*, prev_block should now "be" state, correct? But it doesn't, because their arrays are different.
state->v[8*12] = 12; printf("%" PRIu64 "\n", (*state)[12]); prev_block = state[12]; printf("%" PRIu64 "\n", (*(&prev_block))[12]); So, what exactly is going on here?
struct blockshould just bestd::array< std::uint64_t, BYTES_IN_BLOCK / sizeof (std::uint64_t) >. The way it's written,block prev_blockmight be misaligned in memory.std::aligned_storageis probably more appropriate