问题描述
(免责声明:在这一点上,这主要是学术兴趣。)
想象我有这样一个外部接口,也就是我不控制它的代码:
// Provided externally: Cannot (easily) change this:
// fill buffer with n floats:
void data_source_external(float* pDataOut,size_t n);
// send n data words from pDataIn:
void data_sink_external(const uint32_t* pDataIn,size_t n);
在标准 C++ 中是否可以在不复制的情况下在这两个接口之间“移动”/“流式传输”数据?
也就是说,有没有办法让下面的内容成为非 UB,而不需要在两个正确类型的缓冲区之间复制数据?
int main()
{
constexpr size_t n = 64;
float fbuffer[n];
data_source_external(fbuffer,n);
// These hold and can be checked statically:
static_assert(sizeof(float) == sizeof(uint32_t),"same size");
static_assert(alignof(float) == alignof(uint32_t),"same alignment");
static_assert(std::numeric_limits<float>::is_iec559 == true,"IEEE 754");
// This is clearly UB. Any way to make this work without copying the data?
const uint32_t* buffer_alias = static_cast<uint32_t*>(static_cast<void*>(fbuffer));
// **Note**:
// + reinterpret_cast would also be UB.
data_sink_external(buffer_alias,n);
// ...
据我所知,以下是定义的行为,至少在严格别名方面:
...
uint32_t ibuffer[n];
std::memcpy(ibuffer,fbuffer,n * sizeof(uint32_t));
data_sink_external(ibuffer,n);
但考虑到 ibuffer
将与 fbuffer
具有完全相同的位,这似乎很疯狂。
或者我们会expect optimizing compilers to optimize甚至把这个副本拿走吗? (在现已删除的类似评论的回答中,用户发布了一个 godbolt link,至少乍一看似乎表明 clang 11 确实能够优化 memcpy。)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)