reinterpret_cast用法操纵字节
我正在阅读在这里如何使用byteswap
功能。我不明白为什么实际需要bit_cast
,而不是使用reinterpret_cast
to char*
。我了解的是,使用这种演员,我们没有违反严格的混叠规则。我读到下面的第二个版本可能是错误的,因为我们可以访问未对齐的内存。可以,但是在这一点上,我有点困惑,因为如果访问是由于不一致的内存而引起的,那么何时可以使用reinterpret_cast
来操纵字节?根据标准,演员应允许访问(读/写)内存。
template<std::integral T>
constexpr T byteswap(T value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>,
"T may not have padding bits");
auto value_representation = std::bit_cast<std::array<std::byte, sizeof(T)>>(value);
std::ranges::reverse(value_representation);
return std::bit_cast<T>(value_representation);
}
template<std::integral T>
void byteswap(T& value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>,
"T may not have padding bits");
char* value_representation = reinterpret_cast<char*>(value);
std::reverse(value_representation, value_representation+sizeof(T));
}
I was reading here how to use the byteswap
function. I don't understand why bit_cast
is actually needed instead of using reinterpret_cast
to char*
. What I understand is that using this cast we are not violating the strict aliasing rule. I read that the second version below could be wrong because we access to unaligned memory. It could but at this point I'm a bit confused because if the access is UB due to unaligned memory, when is it possible to manipulate bytes with reinterpret_cast
? According to the standard the cast should allow to access (read/write) the memory.
template<std::integral T>
constexpr T byteswap(T value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>,
"T may not have padding bits");
auto value_representation = std::bit_cast<std::array<std::byte, sizeof(T)>>(value);
std::ranges::reverse(value_representation);
return std::bit_cast<T>(value_representation);
}
template<std::integral T>
void byteswap(T& value) noexcept
{
static_assert(std::has_unique_object_representations_v<T>,
"T may not have padding bits");
char* value_representation = reinterpret_cast<char*>(value);
std::reverse(value_representation, value_representation+sizeof(T));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
主要原因是
reinterpret_cast
不能在恒定的表达评估中使用,而std :: bit_cast
can可以。std :: byteswap
被指定为constexpr
。如果您在实施中的声明中添加了
constexpr
,它将是不正确的,无需诊断,因为它没有专业化,可以称为子表达恒定表达。如果没有
constexpr
它不是不构型的,但不能称为常数表达式的子表达,std :: byteswap
应该允许。此外,标准中存在缺陷:
标准从技术上讲不允许在
reinterpret_cast&lt; char*&gt;(value)
pointer上进行指针算术(也没有真正指定阅读的含义并通过这样的指针写作)。目的是
char*
指针应为对象的对象表示,被视为字符数组。但是目前的标准只是说reinterpret_cast&lt; char*&gt;(value)
指针仍指向原始对象,而不是其对象表示。参见 p1839> p1839 规范更符合通常的假设。来自cppReference的实现也是一个假设,不能保证不正确:是否
std :: array&lt; std :: byte,sizeof(t)&gt;
保证具有与大小相同的大小t
。当然,这应该在实践中保留,如果不这样做,std :: bit_cast
将无法编译。如果您想阅读一些关于是否可以保证它在理论上保证的讨论,请参见问题 std :: bit_cast使用std ::数组,是STD的大小: :由标准定义和 sizeof std :: array; ,n&gt;?
The primary reason is that
reinterpret_cast
can not be used in constant expression evaluation, whilestd::bit_cast
can. Andstd::byteswap
is specified to beconstexpr
.If you added
constexpr
to the declaration in your implementation, it would be ill-formed, no diagnostic required, because there is no specialization of it that could be called as subexpression of a constant expression.Without the
constexpr
it is not ill-formed, but cannot be called as subexpression of a constant expression, whichstd::byteswap
is supposed to allow.Furthermore, there is a defect in the standard:
The standard technically does not allow doing pointer arithmetic on the
reinterpret_cast<char*>(value)
pointer (and also doesn't really specify a meaning for reading and writing through such a pointer).The intention is that the
char*
pointer should be a pointer into the object representation of the object, considered as an array of characters. But currently the standard just says that thereinterpret_cast<char*>(value)
pointer still points to the original object, not its object representation. See P1839 for a paper proposing to correct the specification to be more in line with the usual assumptions.The implementation from cppreference is also making an assumption that might not be guaranteed to be true: Whether
std::array<std::byte, sizeof(T)>
is guaranteed to have the same size asT
. Of course that should hold in practice andstd::bit_cast
will fail to compile if it doesn't.If you want to read some discussion on whether or not it is guaranteed in theory, see the questions std::bit_cast with std::array, Is the size of std::array defined by standard and What is the sizeof std::array<char, N>?