C++ memcpy de double tableau de float array

c'Est possible de faire memcpy à partir d'un tableau double pour un float array en toute sécurité?

10
demandé sur dmessf 2010-06-02 19:18:15

5 réponses

Dépend de ce que vous voulez. Les valeurs ne seront certainement pas préservées. Si vous avez besoin, utilisez 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);
}
31
répondu fredoverflow 2010-06-02 15:19:15

Non.

26
répondu Daniel Daranas 2010-06-02 15:20:32

le problème est qu'il n'y a aucune garantie que la représentation binaire d'un double est la représentation équivalente d'un float. Afin d'utiliser memcpy pour les types à plusieurs octets, la représentation sous-jacente doit être la même (même disposition). Vous pouvez copier floatfloat,intint et doubledouble.

Vous êtes destiné pour comportement non défini lorsque le type source ne correspond pas à la destination tapez, comme copier à partir de longchar ou floatdouble. memcpy la fonction ne fait aucune conversion ou n'exécute aucune promotion. Il copie seulement.

3
répondu Thomas Matthews 2010-06-02 16:41:20

comme beaucoup d'autres ont répondu, en utilisant memcpy ne fonctionne pas puisque les deux types sont (généralement) de taille différente. Pour en savoir plus http://en.cppreference.com/w/cpp/language/types, ou plus précisément:

virgule Flottante types

float - à point flottant de précision simple. Généralement la norme IEEE-754 32 bits à virgule flottante de type

double - double précision type à virgule flottante. Généralement la norme IEEE-754 64 bits à virgule flottante de type

long double - de précision étendue à virgule flottante. Ne correspond pas nécessairement aux types prescrits par IEEE-754. Habituellement le type à virgule flottante x87 de 80 bits sur les architectures x86 et x86-64.

en utilisant std::copy vous donnera un avertissement de compilateur (au moins pour moi sur le compilateur VS2015/VS2017) puisque le compilateur ne permet pas la perte implicite de précision de la double à flotter via std::copy, sans avertissement, le développeur à ce sujet. Et si vous avez l' treat warnings as errors indicateur est défini, vous obtiendrez une erreur de compilation.

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

a la place, je recommande d'utiliser le std::transform fonction, combinée avec un lamda exécutant le moulage spécifique. Cela montre aussi plus clairement qu'une perte de précision explicite est effectivement en cours.

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); });
2
répondu AzP 2018-05-31 09:06:36