c++ - 确定 reinterpret_cast 在编译时是否安全

标签 c++ memcpy reinterpret-cast strict-aliasing

根据reinterpret_cast page on cppreference.com , 有 11 次转化

can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.

所以,我的问题是:是否可以编写一个像这样的 constexpr 函数

template <typename T1, typename T2>
constexpr bool is_reinterpret_cast_safe() {
    // ...
}

根据这 11 个点检查是否允许转换?由于 GCC 和 Clang 等编译器能够检查代码是否违反了严格的别名规则,使用 -fstrict-aliasing -Wstrict-aliasing 进行编译,我认为这应该是可行的。

我知道 C++20 引入了 std::bit_cast , 但它仍然不受任何编译器的支持。在编译时在两个转换函数之间进行选择可能很有用

template <typename T1, typename T2>
T1 f_reinterpret_cast(T2 d) {
    static_assert(sizeof(T1) == sizeof(T2));
    return *reinterpret_cast<T1*>(&d); // could be undefined behavior;
}

template <typename T1, typename T2>
T1 f_memcpy(T2 d) {
    static_assert(sizeof(T1) == sizeof(T2));
    T1 n;
    std::memcpy(&n, &d, sizeof(T2)); // OK
    return n;
}

使用 SFINAE 或 if constexpr:

template <typename T1, typename T2>
T1 conv(T2 d) {
    if constexpr (is_reinterpret_cast_safe<T1, T2>())
        return conv_reinterpret_cast<T1, T2>(d);
    else
        return conv_memcpy<T1, T2>(d);
}

您可以在 https://godbolt.org/z/Ex6GnP 上找到代码.

最佳答案

编译器在编译时检查reinterpret_cast 表达式 的有效性:访问对象时会违反别名规则:

int i = 0;                                   //OK
double j* = reinterpret_cast <double*> (i);  //OK
double k = *j;                               //strict aliasing violation

无法检查 reinterpret_cast 不会导致指针无法用于访问它指向的对象。

关于c++ - 确定 reinterpret_cast 在编译时是否安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62929842/

相关文章:

c++ - QT5连接信号到函数

ios - EXC_BAD_ACCESS 尝试返回 uint64_t 数字时

iphone - memcpy 导致 'exc bad access'

c++ - ZMQ : Sending custom CPP object over the ZMQ queue

c++ - 将 reinterpret_cast 转换为可变大小的数组

c++ - 使用 SOLVEPNP_EPNP 的相机姿态估计是否对异常值敏感,可以纠正吗?

c++ - C++中两个/两个以上对象的重载加法赋值运算符?

C++ STL 比较映射找不到(运算符==)

c++ - 使用 const 变量可以避免别名问题吗

c++ - 从 int64 转换为字节数组