ダブル配列からフロート配列に安全にmemcpyすることは可能ですか?
5 に答える
あなたが望むものに依存します。値は確かに保存されません。それが必要な場合は、を使用して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);
}
問題は、コンパイラのaのバイナリ表現がadouble
の同等の表現であるという保証がないことfloat
です。memcpy
マルチバイトタイプに使用するには、基になる表現が同じ(同じレイアウト)である必要があります。float
、 to float
、int
toint
に安全にコピーできdouble
ますdouble
。
からまたはへのコピーなど、ソースタイプが宛先タイプと一致しない場合、未定義の動作が発生する可能性があります。この関数は、変換やプロモーションを実行しません。コピーするだけです。long
char
float
double
memcpy
他の多くの人が答えているようにmemcpy
、2つのタイプは(一般的に)サイズが異なるため、使用は機能しません。詳細については、 http://en.cppreference.com/w/cpp/language/typesを参照してください。具体的には、次のとおりです。
浮動小数点の種類
float-単精度浮動小数点型。通常、IEEE-75432ビット浮動小数点型
double-倍精度浮動小数点型。通常、IEEE-75464ビット浮動小数点型
longdouble-拡張精度の浮動小数点型。IEEE-754で義務付けられているタイプに必ずしもマップされるとは限りません。通常、x86およびx86-64アーキテクチャでは80ビットx87浮動小数点型です。
コンパイラは、開発者に警告することなく、std :: copyを介してdoubleからfloatへの暗黙的な精度の低下を許可しないため、を使用std::copy
すると、コンパイラに警告が表示されます(少なくともVS2015 / VS2017コンパイラでは)。また、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); });
一般的な場合-いいえ。
特定のケースでは、特定のプラットフォームでfloat
との表現がdouble
同じである可能性があり、コピーは成功します。しかし、とにかくそれは実用的な意味がありません。
memcpy
型にとらわれず(バイトを見るだけ)、型変換を行うことはできません。std::transform
@AzPが言ったように使用してください:
std::transform(a, a + 5, b, [](double d) -> float {return float(d);});