Here is a simple test program that illustrates the problem I faced:
#include <iostream>
#include <stdlib.h>
#include <inttypes.h>
#include <vector>
using namespace std;
typedef unsigned char Byte;
int main( )
{
uint32_t ui32 = 12;
size_t sizeofUi32 = sizeof ui32;
cout << "sizeofUi32: " << sizeofUi32 << endl;
vector<Byte> v(10);
std::copy(&ui32, &ui32 + sizeof ui32, &v[4]);
uint32_t result = 0;
std::copy(&v[4], &v[4] + sizeof ui32, &result);
cout << "Result: " << result << " sizeofUi32: " << sizeofUi32 << endl;
return 0;
}
output:
sizeofUi32: 4
Result: 12 sizeofUi32: 17179869184
I thought this issue might be due to std::copy accepting iterators not pointers, but from what I got in SO here,
a pointer IS an iterator
So there must be a simple issue with my sample code, that I' missing. But I can't spot it. Could you please explain, what's wrong here?
EDIT 1:
So from the answers I got the idea, that to deserialize a vector of bytes, if I know the right order and types of stored data in vector, I can avoid using std::copy and just assign vector values to variables of proper types. It works, but is it safe?
uint32_t a = v[4];
uint8_t b = v[8];
The problem isn’t with
std::copy
but with pointer arithmetic. As you’ve said, “a pointer IS an iterator”. But more importantly, it’s strongly typed. So a pointer-to-uint32_t
is different from a pointer-to-unsigned char
.Adding
&ui32 + sizeof ui32
effectively treatsui32
as if it were the beginning of a contiguous array with 4 elements (of typeuint32_t
).The immediate problem is here:
&ui32
has typeuint32_t *
, and adding anything to that already takes into account the object's size. You're effectively attempting to copysizeof ui32
uint32_t
objects, but you only have a single one, so you should be using+ 1
.That aside, using
std::copy
with pointers of different types is likely not to give you the results you expect. It has the effect ofv[4] = ui32;
, which works as long asui32
is insideByte
's range, which it is here, but that's not something you can rely on in general.The second
std::copy
has roughly the same problem, but in the opposite direction.What you could do is: