我尝试将 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
的生命周期已结束,可能不再使用。
有一个proposal将 std::bless
引入语言中,这样在这种情况下就不需要显式创建对象了。
关于c++ - 从 long 转换为相同大小的 int 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58014104/