c++ - 从 long 转换为相同大小的 int 失败

标签 c++ casting

我尝试将 long 数组转换为相同大小的整数数组 ( godbolt ):

#include <cstdint>
#include <cstddef>
#include <cstring>

template<int> struct sized_int_ {};      
template<> struct sized_int_<8> { typedef int64_t type; };   
template<> struct sized_int_<4> { typedef int32_t type; };
typedef sized_int_<sizeof(long)>::type long_t;              

void funcA(int32_t* array, std::size_t s); // defined somewhere else
void funcA(int64_t* array, std::size_t s); // defined somewhere else

// technically illegal cast
void funcB(long* array, std::size_t s) {
    funcA(static_cast<long_t*>(array), s);
}

// memcpy
void funcC(long* array, std::size_t s) {
    long_t* tmp = new long_t[s];
    memcpy(tmp, array, s*sizeof(long_t));
    funcA(tmp, s);
    delete[] tmp;
}

int main() {
    long x[] = {2, 3};
    static_assert(sizeof(long_t)==sizeof(long), "Sizes don't match");
    funcB(x, 2);
    funcC(x, 2);
    return 0;
}

g++ 愉快地接受代码,但 MacOS 上的 clang 不接受(error: static_cast from 'long *' to 'long_t *' (aka 'long long *') is not allowed)。 reinterpret_cast 在这两种情况下都有效,但它也允许我从 int32_t* 转换为 int64_t*

至少 clang 和 gcc 使用 -O2 没有优化分配临时数组并将数据复制到其中的正确方法。

如何将 long* 安全地转换为相应的 intX_t*

最佳答案

How can I cast long to the corresponding intX_t safely?

你不需要施法。转换是隐式的:

long x = 2;
long_t y = x;

但是如果你想显式的话你可以使用静态转换:

long_t y = static_cast<long_t>(x);

指针欺骗意味着您可能想就地处理对象。这当然要求类型具有相同的表示,这是相当合理的假设,但不能保证。但即使是这样的假设在技术上也不足以根据标准很好地定义通过 reinterpret_cast 的间接寻址。

您可以通过创建所需类型的对象在技术上重用存储:

long_t temp = x;
long_t* reused_x = new(&x) long_t(temp);

重用后,如果不能通过清洗存储 placement new 返回的指针,则可以将指针动态转换为 x。请注意,如果没有上面的新展示位置,洗钱是不够的。

long_t* converted = std::launder(reinterpret_cast<long_t*>(&x));

同样可以在数组循环中完成:

template<class T, class F> // types To and From
T* reuse_array(F* first, F* last, T* d_first) {
    for (F* ptr = first; ptr != last; ++d_first, (void) ++ptr) {
        T value = *ptr;
       ::new (ptr) T(value);
    }
   return std::launder(reinterpret_cast<T*>(first));
}

这甚至可以通过使用 std::memcpy 的结构来完成,只要它们是普通可复制和可破坏的。一个相当好的优化器应该 elide the copies .请注意,x 的生命周期已结束,可能不再使用。

有一个proposalstd::bless 引入语言中,这样在这种情况下就不需要显式创建对象了。

关于c++ - 从 long 转换为相同大小的 int 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58014104/

相关文章:

c++ - Qt: C++: 恢复弹出对话框的几何形状

你能假设类型转换指针是安全的吗?

c++ - 如何使用多个源文件通过 gcc 创建单个目标文件

javascript - 当 JS 代码在应用程序构建时未知时从 QML 调用 JS 函数(帽子提示 SpiderMonkey)

类型别名的 Go 类型开关

c - 如何手动(按位)执行(float)x?

c++ - 如何知道列表中对象的类型?

将 char 指针转换为 int 指针 - 缓冲区错误 10

c++ - 将自定义样式表应用于 QTextDocument

c++ - 使用 Visual Studio 2019 和 cmake for x86 编译 pe-parse 库