Converting uint16_t * array to std::vector

Viewed 1035

I am having trouble converting a pointer array of uint16_t to std::vector<uint16_t> because of integer size issues.

        auto *arr = static_cast<const uint16_t *>(some_method.getArray());
        std::vector<uint16_t> vec(arr, sizeof arr / sizeof arr[0]);

In the first line I obtain a const uint16_t* array. In the second line I initialize the vector using the iterator constructor and pass in the pointer array arr and length of the array (size of the array divided by size of the first element = length of array).

However, c++ wants me to cast arr to unsigned long. So here it is with the cast

        std::vector<uint16_t> vec((unsigned long) arr, sizeof arr / sizeof arr[0]);

It seems to me something bad will happen casting from uint16_t (2 bytes) -> unsigned long (4 bytes) -> uint16_t (2 bytes). Is there a better way to do this array conversion?

Edit: Thank you all for the valuable feedback, the main issues I had:

  1. sizeof gets the size of the pointer, not the length of the array.

  2. I was using the wrong constructor

3 Answers

uint16_t* arr; is not an array, but is a pointer to array located in memory. The sizeof of this pointer is an integer containing an address, always equals 4. Or something else depending on architecture. But always the same constant, not the size of the array.

cout<< sizeof(arr)<< endl; // the output is 4

And sizeof(arr[0]) is a size of an 16 bit integer, so is always 2. Then sizeof arr / sizeof arr[0] will be always 2.
Probably your method some_method.getArray() returning an array of some size, you should have that size contained in some num_of_elements variable. So use that num_of_elements

std::vector<uint16_t> vec(arr, arr + num_of_elements);

To create a vector you need to know the size of the vector. So you can create a vector from an array because you know the size of the array.

But you don't have an array, you have a pointer. You cannot know the size of an array from a pointer, so your task is impossible from the information you have given.

Now maybe you have some other way to know the size of the array, if you do then you can create the vector. Please update the question if appropriate.

First this line is worrisome:

auto *arr = static_cast<const uint16_t *>(some_method.getArray());

You shouldn't need static_cast here, either getArray() returns uint16_t* or not.

Secondly consider rather:

auto [*arr, size] = some_method.getArray());

As you need size of array you are working on. You can't depend on sizeof pointer to return size of array you are thinking of. It works only in localscope in c, othervise it will return size of pointer not array.

Finally, depending on what you really want to do:

#include <cstdint>
#include <vector>
#include <iostream>
#include <array>
#include <tuple>

// 1. you probably don't want that:
// assigning values back from array by pointers to array to vector
std::tuple<uint16_t **, ssize_t> getArray();
auto [array, size] = getArray();
std::vector<uint16_t> v(size);
for (unsigned int i = 0; i < size; ++i) {
  v[i] = *(array[i]);
}

// 2. you probably wanted to do it like that
// this function returns pointer to first element in array
std::tuple<uint16_t *, ssize_t> getArray();
auto [array, size] = getArray();
std::vector<uint16_t> v(size);
for (unsigned int i = 0; i < size; ++i) {
  v[i] = *array;
  ++array;
}


// 3. this is the way you probably should do it
// this one returns begin and end of array and is most probable what you wanted to do
std::tuple<std::uint16_t*, std::uint16_t*> getArray()
{
    // please mind that this static arrays data is just to show that there are
    // somewhere data and these won't be lost because we created them temporarily
    // and that we don't need to release them because somebody meant to pass memory 
    static const ssize_t size = 16;
    static std::uint16_t vals[size] = {1};
    return {vals, vals + size};
}

auto [first, last] = getArray();
std::vector<std::uint16_t> v(first, last);

Related