Могу ли я использовать std :: copy для копирования битового массива данных из вектора целых в массив без знака

Недавно я пытался обновить некоторый код, чтобы использовать стандартные библиотечные функции C ++, а не старые функции стиля C. В частности, я попытался сделать следующее (искусственный рабочий пример для простоты — я знаю, что код некрасив, но он иллюстрирует проблему кратко):

std::vector<int> vData;
vData.push_back(10990);
vData.push_back(11990);
vData.push_back(12990);
vData.push_back(13990);

unsigned char szBuffer[100];
memset(szBuffer,0,sizeof(szBuffer));

std::copy(vData.begin(),vData.end(),szBuffer);

Я ожидал, что это будет вести себя аналогично коду, который я пытаюсь заменить:

memcpy(szBuffer,&vData[0],sizeof(int)*vData.size());

но отладка кода, ясно, что std::copy код, который я написал, записывает только первые 4 байта unsigned char буфер вместо полной битовой комбинации из 4 целых чисел в векторе. Может кто-нибудь сказать мне, что я сделал неправильно, или это просто, что я не могу использовать std::copy таким образом и должен придерживаться memcpy ?

1

Решение

Придерживаться memcpy, std::copy быть умным, он понимает вовлеченные типы и правильно преобразовывает int в unsigned char используя стандартные преобразования. memcpy невежественен, это то, что вы хотите.

4

Другие решения

Я ожидал, что это будет вести себя аналогично коду, который я пытаюсь заменить …

Тот std::copy как написано не может вести себя так же, как std::memcpy или же std::memmove потому что несоответствие типов между элементами std::vector<int> по сравнению с элементами unsigned char szBuffer[100], Один из способов преодолеть это несоответствие типов — это szBuffer для int*:

std::copy(vData.begin(),vData.end(),reinterpret_cast<int*>(szBuffer));

Тот reinterpret_cast это вопрос личных предпочтений. Я бы предпочел увидеть что-то, что кричит «Опасность, опасность, Уилл Робинсон!» для чего-то, что может вызывать неопределенное поведение над приведением в стиле C, которое скрывает, но не удаляет потенциал для UB. Я (и мои руководители проекта) могу grep для reinterpret_cast,

Потенциал для UB здесь реален, так как нет никакой гарантии, что этот бросок действителен из-за проблем с выравниванием.

Обратите внимание, что нет никакой гарантии, что std::copy когда-либо будет реализован через memcpy или же memmove, В стандарте нет ни одного слова (2003 или 2011), которое бы гласило, что std::copy должен быть реализован через memcpy или же memmove если возможно. (В сторону: в каждой реализации, которую я видел, std::copy будет осуществляться через std::memmove если это будет работать «как если бы» была применена наивная реализация.)

Единственная причина, чтобы перейти от std::memcpy в std::copy вот эстетика. Иногда эстетика мешает. «Глупая последовательность — это хобгоблин маленьких умов». Я рекомендую придерживаться std::memcpy, Он делает именно то, что вы хотите, и это использование безопасно, потому что нет перекрытия и потому что буфер имеет правильный размер.

2

потому что стандартом является то, что поведение (если не точная реализация)
std::copy эквивалентно:

namespace std {
template< typename InIter, typename OutIter >
OutIter std::copy( InIter begin, InIter end, OutIter outp )
{
for( ; begin != end; ++begin, ++outp )
{
*outp = *begin;
}
return outp;
}
}

это означает, что он копирует элемент за элементом, увеличивая каждый итератор и возвращает следующую позицию записи в выводе.

Это не то же самое поведение, что и у memcpy, что вам и нужно. Нет ничего плохого в использовании memcpy (даже если некий компилятор Microsoft скажет вам, что это небезопасно, что может быть, но то же самое относится к управлению грузовиком, если вы не ведете его должным образом, это не значит, что никто никогда не сможет управлять им) ,

1

Чтобы интерпретировать содержимое вектора как необработанную память, используйте reinterpret_cast в unsigned char *:

std::copy(reinterpret_cast<unsigned char *>(&*vData.begin()),
reinterpret_cast<unsigned char *>(&*vData.end()), szBuffer);

Вы должны косвенно и взять адрес начала и конца элементов, потому что это не гарантирует, что vector::iterator тип указателя

Это одно из немногих гарантированных безопасных применений reinterpret_cast,

1
По вопросам рекламы [email protected]