C ++ memcpy从double数组到float数组

时间:2010-06-02 15:18:16

标签: c++ memcpy

是否可以安全地从双数组到浮点数组进行memcpy?

5 个答案:

答案 0 :(得分:31)

取决于你想要什么。这些价值肯定不会被保留。如果需要,请使用std::copy

#include <algorithm>

int main()
{
    double a[] = {1.618, 3.1416, 2.7, 0.707, 1.0};
    float b[5];
    std::copy(a, a + 5, b);
}

答案 1 :(得分:4)

问题在于无法保证编译器的double的二进制表示是float的等效表示。为了使用memcpy多字节类型,底层表示必须相同(相同的布局)。您可以安全地将float复制到float,将int复制到int,将double复制到double

当源类型与目标类型不匹配时,您将注定未定义的行为,例如从long复制到charfloat到{ {1}}。 double功能不会进行任何转化或执行任何促销活动。它只是复制。

答案 2 :(得分:2)

与其他许多人一样,使用memcpy不起作用,因为这两种类型(通常)大小不同。请在http://en.cppreference.com/w/cpp/language/types上查看更多信息,或者更具体地说:

  

浮点类型

     

float - 单精度浮点类型。   通常是IEEE-754 32位浮点类型

     

double - 双精度浮点类型。通常是IEEE-754 64位浮点类型

     

long double - 扩展精度浮点类型。不一定映射到IEEE-754规定的类型。通常是x86和x86-64架构上的80位x87浮点类型。

使用std::copy将为您提供编译器警告(至少对我来说VS2015 / VS2017编译器),因为编译器不允许通过std :: copy从double到float的隐式精度损失,而不会发出警告关于它的开发者。如果设置了treat warnings as errors标志,则会出现编译错误。

1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xutility(2316): error C2220: warning treated as error - no 'object' file generated
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xutility(2335): note: see reference to function template instantiation '_OutIt std::_Copy_unchecked1<_InIt,_OutIt>(_InIt,_InIt,_OutIt,std::_General_ptr_iterator_tag)' being compiled
1>        with
1>        [
1>            _OutIt=float *,
1>            _InIt=double *
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xutility(2354): note: see reference to function template instantiation '_OutIt *std::_Copy_unchecked<_InIt,float*>(_InIt,_InIt,_OutIt)' being compiled
1>        with
1>        [
1>            _OutIt=float *,
1>            _InIt=double *
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xutility(2364): note: see reference to function template instantiation '_OutIt std::_Copy_no_deprecate1<double*,_OutIt>(_InIt,_InIt,_OutIt,std::random_access_iterator_tag,std::random_access_iterator_tag)' being compiled
1>        with
1>        [
1>            _OutIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<float>>>,
1>            _InIt=double *
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xutility(2373): note: see reference to function template instantiation '_OutIt std::_Copy_no_deprecate<_InIt,_OutIt>(_InIt,_InIt,_OutIt)' being compiled
1>        with
1>        [
1>            _OutIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<float>>>,
1>            _InIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>
1>        ]
1>test.cpp(153): note: see reference to function template instantiation '_OutIt std::copy<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>,std::_Vector_iterator<std::_Vector_val<std::_Simple_types<float>>>>(_InIt,_InIt,_OutIt)' being compiled
1>        with
1>        [
1>            _OutIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<float>>>,
1>            _InIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xutility(2316): warning C4244: '=': conversion from 'double' to 'float', possible loss of data

相反,我建议使用std::transform函数,并结合执行特定强制转换的lamda。这也更清楚地表明实际上正在发生明显的精度损失。

std::vector<double> doubles = { 5.0, 10.0, 242.130, 42.0 };
std::vector<float> floats(doubles.size());
std::transform(std::begin(doubles), std::end(doubles), std::begin(floats), [&](const double& value) { return static_cast<float>(value); });

答案 3 :(得分:1)

一般情况下 - 没有。

在特定情况下,在给定平台上,floatdouble的表示可能相同,副本也会成功。但无论如何它都没有任何实际意义。

答案 4 :(得分:1)

memcpy是类型无关的(仅能看到字节),并且不能进行类型转换。就像@AzP所说的那样使用std::transform

std::transform(a, a + 5, b, [](double d) -> float {return float(d);});