Replacing reinterpret_cast by memcpy

176 Views Asked by At

I've got some legacy code containing the following line of code:

uint16_t* data = reinterpret_cast<uint16_t*>(array_.data()); // #1

With array_ of type std::vector. So far, I understood that we store into data a pointer to the first element of the vector, and we tell the compiler to consider it as an uint16_t.

For some reasons, I'm looking to replace the reinterpret_cast by a memcpy.

I've come along with the following replacement lines:

uint16_t* data;
memcpy(&data, typed_array_.data(), bytes_per_elem); // #2

With bytes_per_elem the size in bytes of vector elements.

I'm not very fluent with the use of reinterpret_cast and memcpy, so I'd like to know, can I consider #1 and #2 as equivalent?

3

There are 3 best solutions below

0
KamilCuk On BEST ANSWER

can i consider #1 and #2 as equivalent ?

No, the #2 code looks very invalid. It tries to interpret the data stored in a vector as a pointer value to uint16_t. Which the first interprets the data stored in the vector as values of uint16_t, not a pointer value.

I guess you probably meant to allocate the memory to store the actual data:

// assuming std::vector<uint8_t> array_;
std::vector<uint16_t> data(array_.size() / sizeof(uint16_t));
memcpy(data.data(), array_.data(), array_.size());

But it would be much better to do the actual conversion, like:

// assuming std::vector<uint8_t> array_;
std::vector<uint16_t> data(array_.size() / sizeof(uint16_t));
for (size_t i = 0; i < array_.size(); i += 2) {
    // little endian or big endian?
    data[i / 2] = array_[i] << 8 | array_[i + 1];
}

Consider researching strict aliasing rules, reinterpret_cast, how does pointers differ from values, what is & operator in C++, <bit>, std::byte, std::bit_cast.

2
Yousha Aleayoub On

The code using reinterpret_cast and the replacement code using memcpy are NOT equivalent.

The line using reinterpret_cast does not perform any data copying; it simply changes the type of the pointer. Both pointers are pointing to the same memory location.

The line using memcpy() is attempting to copy data from the memory location which typed_array_.data() is pointing at, to the memory location occupied by data itself, not to where data is pointing at (which is nowhere).

Note that the destination pointer data is uninitialized, so the behavior is undefined.

0
rain 183 On

Even if we wouldn t consider your errors, the two snippets act differently. The first, it s nothing more than pointer type conversion. In C converting from integral type to pointer, pointer to integral type or from pointer to pointer of different type is just fine, in C++ it's not. Here comes reinterpret_cast, which force the compiler to do that operation. Such operation may be unsafe, that's why the compiler asks you to explicitly declare the conversion. In the second example there is an error, you just declared the pointer but it is not initialized. To initialize the pointer you have three ways: declaring an array big enough(probably the worst), declaring an array with the new[] operator (remember you must free the memory with delete[]), or declaring a std::vector<uint16_t> and reserve the needed space. That said, in the memcpy call, the last parameter is the total number of bytes, not the bytes per element