Often in C++, one has a parameter void* user_data that one can use to pass an arbitrary type.
I used this to pass an array of booleans. However, I had a bug where I cast from bool* --> void* --> int* and I got weird results. Here is an example.
#include <iostream>
int main() {
bool test[2] = { };
void *ptr = static_cast<void*>(test);
std::cout << static_cast<bool*>(ptr)[0] << '\n';
std::cout << static_cast<int*>(ptr)[0] << '\n';
std::cout << static_cast<int>(test[0]) << '\n';
}
Output:
$ g++ int_bool.cpp
$ ./a.out
0
-620756992
0
Can someone explain to me what the problem is? Normally when I cast from bool to int, there is no problem: false maps to 0 and true maps to 1. Clearly, that's not the case here.
static_cast<int*>(ptr)[0]castsptrtoint*and reads the first element. Since the original array is only 2 bytes, you're reading outside it (because you're reading a 4-byteint) and invokes undefined behavior, unlessintis a 2-byte type on your system. You're also violating the strict aliasing rule by accessing a type using a different pointer type which also invokes UB. Besides you'll get UB if the bool array isn't properly aligned. On x86 it doesn't cause any problems because x86 allows unaligned access by default but you'll get a segfault on most other architecturesstatic_cast<int>(test[0])OTOH convertstest[0](which is abool) tointand is a completely valid value conversion.Update:
No. When dereferencing a variable
var, an amount of memory of lengthsizeof(var)will be read from memory starting from that address and treat as the value of that variable. So*bool_ptrwill read 1 byte and*int_ptrwill read 4 bytes from memory (ifboolandintare 1 and 4-byte types respectively)In your case the
boolarray contains 2 bytes, so when 4 bytes is read fromstatic_cast<int*>(ptr), 2 byte inside the array and 2 bytes outside the array are read. If you declaredbool test[4] = {};(or more elements) you'll see that theint*dereferencing completes successfully because it reads all 4 bools that belong to you, but you still suffer from the unalignment issueNow try changing the bool values to nonzero and see
You'll quickly realize that casting a pointer to a different pointer type isn't a simple read in the old type and convert to the new type like a simple value conversion (i.e. a cast) but a different "memory treatment". This is essentially just a
reinterpret_castwhich you can read to understand more about this problemCasting from any other pointer types to
char*is valid. Read the question about strict aliasing rule above:It's used for things like
memcpywhere you copy the bytes representing a type to a different destinationTechnically
mempcyreceivesvoid*, the cast tochar*is just used for demonstrationSee also