12

ダブル配列からフロート配列に安全にmemcpyすることは可能ですか?

4

5 に答える 5

32

あなたが望むものに依存します。値は確かに保存されません。それが必要な場合は、を使用して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);
}
于 2010-06-02T15:19:15.420 に答える
4

問題は、コンパイラのaのバイナリ表現がadoubleの同等の表現であるという保証がないことfloatです。memcpyマルチバイトタイプに使用するには、基になる表現が同じ(同じレイアウト)である必要があります。float、 to floatinttointに安全にコピーできdoubleますdouble

からまたはへのコピーなど、ソースタイプが宛先タイプと一致しない場合、未定義の動作が発生する可能性があります。この関数は、変換やプロモーションを実行しません。コピーするだけです。longcharfloatdoublememcpy

于 2010-06-02T16:41:20.017 に答える
2

他の多くの人が答えているように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); });
于 2018-05-31T08:30:56.147 に答える
1

一般的な場合-いいえ。

特定のケースでは、特定のプラットフォームでfloatとの表現がdouble同じである可能性があり、コピーは成功します。しかし、とにかくそれは実用的な意味がありません。

于 2010-06-02T16:52:10.617 に答える
1

memcpy型にとらわれず(バイトを見るだけ)、型変換を行うことはできません。std::transform@AzPが言ったように使用してください:

std::transform(a, a + 5, b, [](double d) -> float {return float(d);});
于 2018-12-18T22:07:54.307 に答える