C++ memcpy из двойного массива в массив float
можно ли безопасно memcpy из двойного массива в массив float?
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);
}
проблема в том, что нет никакой гарантии, что двоичное представление составителя о double
является эквивалентным представлением float
. Для того, чтобы использовать memcpy
для многобайтовых типов является то, что базовое представление должно быть таким же (такой же планировки). Вы можете смело копировать float
to float
, int
to int
и double
до double
.
тебе суждено неопределенное поведение когда тип источника не соответствует назначению введите, например, копирование из long
to char
или float
to double
. The memcpy
функция не делает никакого преобразования или выполнять какие-либо акции. Он просто копирует.
как и многие другие ответили, используя memcpy
не работает, так как два типа (как правило) отличаются по размеру. Пожалуйста, смотрите больше на http://en.cppreference.com/w/cpp/language/types, или более конкретно:
типы с плавающей запятой
float - одиночный тип с плавающей запятой точности. Обычно IEEE-754 32-битный тип с плавающей запятой
двойной - двойной точности тип с плавающей запятой. Обычно IEEE-754 64 бит с плавающей запятой типа
двойной - выдвинутый тип с плавающей запятой точности. Не обязательно сопоставляется с типами, уполномоченными IEEE-754. Обычно 80-битный тип с плавающей запятой x87 на архитектурах x86 и x86-64.
используя std::copy
даст вам предупреждение компилятора (по крайней мере, для меня на компиляторе VS2015/VS2017), так как компилятор не позволяет неявную потерю точности от double до float через std:: copy, без предупреждения разработчика об этом. И если у вас есть 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
функция, совмещенная с ламда выполняя специфическое бросание. Это также более ясно показывает, что на самом деле происходит явная потеря точности.
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
может быть то же самое, и копия будет успешной. Но в любом случае это не имеет никакого практического смысла.