reinterpret_cast用法操纵字节

发布于 2025-02-11 00:44:18 字数 1184 浏览 1 评论 0原文

我正在阅读在这里如何使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

著墨染雨君画夕 2025-02-18 00:44:18

主要原因是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, while std::bit_cast can. And std::byteswap is specified to be constexpr.

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, which std::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 the reinterpret_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 as T. Of course that should hold in practice and std::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>?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文