I was reading this excellent material about the strict aliasing rule: or
But in the section about std::bit_cast and an alleged limitation of std::bit_cast
, I don't understand the need for both a std::memcpy
and a std::bit_cast
.
The provided example seemed a bit contrived and can be simplified to:
#include <bit>
#include <cstring>
struct some_chars {
unsigned char arr[sizeof(unsigned int)] = {};
};
unsigned int foo(unsigned char *p) {
some_chars a;
std::memcpy(a.arr, p, sizeof(unsigned int));
unsigned int result = std::bit_cast<unsigned int>(a);
return result;
}
(see here)
(Here and in the following, p
is assumed to point to a storage of at least sizeof(unsigned int)
unsigned char
)
I'm finding the purpose of the intermediate struct
unclear. What would be wrong with the following?
unsigned int foo(unsigned char *p) {
unsigned int result;
std::memcpy(&result, p, sizeof(unsigned int));
return result;
}
why not std::memcpy
directly into an unsigned int
as illustrated in cpprefence?
// reinterpreting
double d = 0.1;
// std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation
std::int64_t n;
std::memcpy(&n, &d, sizeof d); // OK
LIVE
I was reading this excellent material about the strict aliasing rule: https://stackoverflow/a/51228315/21691539 or https://gist.github/shafik/a956a17d00024b32b35634eeba1eb49e
But in the section about std::bit_cast and an alleged limitation of std::bit_cast
, I don't understand the need for both a std::memcpy
and a std::bit_cast
.
The provided example seemed a bit contrived and can be simplified to:
#include <bit>
#include <cstring>
struct some_chars {
unsigned char arr[sizeof(unsigned int)] = {};
};
unsigned int foo(unsigned char *p) {
some_chars a;
std::memcpy(a.arr, p, sizeof(unsigned int));
unsigned int result = std::bit_cast<unsigned int>(a);
return result;
}
(see here)
(Here and in the following, p
is assumed to point to a storage of at least sizeof(unsigned int)
unsigned char
)
I'm finding the purpose of the intermediate struct
unclear. What would be wrong with the following?
unsigned int foo(unsigned char *p) {
unsigned int result;
std::memcpy(&result, p, sizeof(unsigned int));
return result;
}
why not std::memcpy
directly into an unsigned int
as illustrated in cpprefence?
// reinterpreting
double d = 0.1;
// std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation
std::int64_t n;
std::memcpy(&n, &d, sizeof d); // OK
LIVE
Share Improve this question asked 1 hour ago OerstedOersted 2,6446 silver badges26 bronze badges1 Answer
Reset to default 1bit_cast
is for converting the object representation of one type to another type. But bit_cast
requires having a live object of the source type. And the source type must be a value type.
p
is a pointer to some bytes. And while p
itself is a value type, which it points to isn't. bit_cast
needs a value type, so you have to copy the desired bytes into a value type and then perform the cast.
What would be wrong with the following?
memcpy
ing into a live object is only permitted to work by the standard if the source bits came from a live object of that type, as described in [basic.types]/2&3. So if p
pointed to data that is an object representation of an unsigned int
created by a copy from a valid unsigned int
, then it does work. But if p
pointed to, say, various bits you loaded from a file or got from the internet or wherever, then as far as the standard is concerned, all bets are off.
bit_cast
is less restrictive; as long as the bits represent a valid value of the new type, bit_cast
will manifest that value in the returned object type.