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 может быть то же самое, и копия будет успешной. Но в любом случае это не имеет никакого практического смысла.