C++ C++;memcpy从双数组到浮点数组

C++ C++;memcpy从双数组到浮点数组,c++,memcpy,C++,Memcpy,是否可以安全地从双数组memcpy存储到浮点数组 取决于你想要什么。这些值肯定不会被保留。如果需要,请使用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); } #包括 int main() { 双a[]={1.618,3.1416,2.7,0.707,1.

是否可以安全地从双数组memcpy存储到浮点数组

取决于你想要什么。这些值肯定不会被保留。如果需要,请使用
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);
}
#包括
int main()
{
双a[]={1.618,3.1416,2.7,0.707,1.0};
浮动b[5];
标准:副本(a,a+5,b);
}

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

当源类型与目标类型不匹配时,您注定要执行未定义的行为,例如从
long
复制到
char
float
复制到
double
memcpy
功能不进行任何转换或执行任何升级。它只是复制。

在一般情况下-否


在特定情况下,在给定平台上,
float
double
的表示可能是相同的,复制将成功。但是它没有任何实际意义。

就像许多其他人回答的那样,使用
memcpy
不起作用,因为这两种类型(通常)大小不同。请参阅或更具体地查看:

浮点类型

浮点型-单精度浮点型。 通常为IEEE-754 32位浮点型

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

长双精度-扩展精度浮点类型。不一定映射到IEEE-754规定的类型。x86和x86-64体系结构上通常为80位x87浮点类型

使用
std::copy
会给您一个编译器警告(至少对我在VS2015/VS2017编译器上是这样),因为编译器不允许通过std::copy从double隐式丢失精度到float,而不会向开发人员发出警告。如果设置了
将警告视为错误
标志,则会出现编译器错误

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

memcpy
与类型无关(只查看字节),无法进行类型转换。只需使用@AzP所说的
std::transform

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

取决于您所说的安全。这不起作用(对于我在VS2017上),因为编译器不允许通过
std::copy
从双精度到浮点精度的隐式损失。我不得不改用
std::transform
函数,使用lamda。这也更清楚地表明确实发生了显式的精度损失。@AzP听起来你选择了编译器选项,让它拒绝有效代码。(或者有一个编译器错误)@M.M好吧,隐式精度损失有点危险-取决于您使用的是什么-使用警告级别4将导致编译器警告。因为我使用的是“将警告视为错误”,所以它不会编译。从这个意义上讲,“有效代码”并不意味着“好代码”。您的问题在于“将警告视为错误”这一荒谬的选项。当然,
transform
有效,更为明确,因此在某些代码库中可能更受欢迎,但是
copy
的“不起作用”显然是错误的。@Marglisse,是的,我将更改该措辞。不过,我不同意这种选择是“荒谬的”。
std::transform(a, a + 5, b, [](double d) -> float {return float(d);});