I want to use fixed contiguous bytes of a long byte array s
as keys in a std::map<std::array<char,N>,int>
.
Can I do this without copying by reinterpreting subarrays of s
as std::array<char,N>
?
Here is a minimal example:
#include <map>
int main() {
std::map<std::array<char,10>,int> m;
const char* s="Some long contiguous data";
// reinterpret some contiguous 10 bytes of s as std::array<char,10>
// Is this UB or valid?
const std::array<char,10>& key=*reinterpret_cast<const std::array<char,10>*>(s+5);
m[key]=1;
}
I would say yes, because char
is a POD type that does not require alignment to specific addresses (in contrast to bigger POD types, see https://stackoverflow.com/a/32590117/6212870). Therefore, it should be OK to reinterpret_cast
to std::array<char,N>
starting at every address as long as the covered bytes are still a subrange of s
, i.e. as long as I ensure that I do not have buffer overflow.
Can I really do such reinterpret_cast
or is it UB?
EDIT:
In the comments, people correctly pointed to the fact that I cannot know for sure that for std::array<char,10> arr
it holds that (void*)&arr==(void*)&arr[0]
due to the possibility of padding of the internal c-array data member of the std::array
template class, even though this typically should not be the case, especially since we are considering a char
POD array. So I update my question:
Can I rely on the reinterpret_cast
as done above when I check via static_assert
that indeed there is no padding? Of coures the code won't compile anymore on compiler/platform combinations where there is padding, so I won't use this method. But I want to know: Are there other concerns apart from the padding? Or is the code valid with a static_assert
check?
(&i)->i // OK???;`. It is not, except that it is a lil bit underspecified. Size, alignment of `S` are unrelated.– Language Lawyer Dec 10 '21 at 15:33(&i)` has no subobjects. And now it is implicit UB.– Language Lawyer Dec 10 '21 at 15:41