Roman
Roman

Reputation: 1513

casting char-array into array of PODs in C++

What's the correct way to write the code below?

I have a memory manager which provides me with char *'s, but I need to work with arrays of uint32_t. How can I work around the strict aliasing rule? I understand that with a single object it's advised just to copy the contents with memcpy() but that solution is not acceptable for an array of objects.

char* ptr = manager()->Allocate(1000 * sizeof(uint32_));
uint32_t* u32ptr = reinterpret_cast<uint32_t*>(ptr);
....
u32ptr[x] = y;

Upvotes: 3

Views: 359

Answers (2)

alain
alain

Reputation: 12047

You can use placement-new:

uint32_t* u32ptr = new(ptr) uint32_t[1000];

Note that after this, the effective type of the storage is uint32_t, and you may not use ptr any more. You don't have to do anything special with the chars, because for types with a trivial destructor, you can end their lifetime simply by reusing the storage.

Upvotes: 6

einpoklum
einpoklum

Reputation: 131986

You could make the Manager class return std::unique_ptr<void, Manager::Deleter>( that is, with a unique pointer with a custom deleter). This makes the allocation use RAII to automagically deallocate when you go out of scope. And instead of using a pointer, prefer a gsl::span In that case, you could write:

constexpr const length = 1000;
auto allocated = manager()->Allocate(
    length * sizeof(std::uint32_t), 
    alignof(uint32_t) // supporting alignment here is important, otherwise
                      // you'll have to manually take care of that yourself
);
auto p = gsl::span<uint32_t>(new(allocated.get()) std::uint32_t[length], length);

Another alternative is to template the Manager class, or the allocation method, on an element type, and have it take care of things:

auto p = manager()->Allocate<std::uint32_t>(1000);

... and p will be an std::unique_ptr<uint32_t> to costructed uint32_ts. Not that you need any construction for them, but still.

Caveat: In both cases, you must not return p from the scope you're in, since it is a non-owning pointer, and the memory will be freed when you leave the scope. p is for local work only. If you want to keep the memory out-of-scope you have to return the unique_ptr.

Upvotes: 1

Related Questions