4

I have my C# code that returns uint array but I want to do it in C++. I looked other posts; they use uint pointer array where my array is not. Does anyone know how to return uint16_t array properly?

This is C# code works fine

  public static UInt16[] GetIntArrayFromByteArray(byte[] byteArray)
        {
            if ((byteArray.Length % 2) == 1)
                Array.Resize(ref byteArray, byteArray.Length + 1);


            UInt16[] intArray = new UInt16[byteArray.Length / 2];


            for (int i = 0; i < byteArray.Length; i += 2)
                intArray[i / 2] = (UInt16)((byteArray[i] << 8) | byteArray[i + 1]);


            return intArray;
        }

This is C++ code that creates syntax error

uint16_t[] GetIntArrayFromByteArray(byte[] byteArray)
{
    //if ((byteArray.Length % 2) == 1)
        //Array.Resize(ref byteArray, byteArray.Length + 1);


    uint16_t[] intArray = new uint16_t[10];


    for (int i = 0; i < 10; i += 2)
        intArray[i / 2] = (uint16_t)((byteArray[i] << 8) | byteArray[i + 1]);


    return intArray;
}
Selen
  • 210
  • 2
  • 16
  • 1
    What is the syntax error? – πάντα ῥεῖ Aug 22 '19 at 10:54
  • 1
    @πάνταῥεῖ says ; is needed because of the return syntax – Selen Aug 22 '19 at 10:55
  • 7
    How about using `std::array` or `std::vector` – JVApen Aug 22 '19 at 10:56
  • @JVApen I am new to c++, I don't understand how can I integrate those two with uint16_t ? – Selen Aug 22 '19 at 10:58
  • 1
    You [need to get a good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). As shown, it will be logically impossible for you to know how big `byteArray` is. Arrays don't have anythng called "Length" in C++. And if you don't know how you can "integrate", that's exactly what a good C++ book will teach you. That's what it's there for. stackoverflow.com isn't unfortunately, an interactive web site that teaches you C++. Only a good book does that. – Sam Varshavchik Aug 22 '19 at 10:59
  • @SamVarshavchik I can fix it, but the main problem is not that – Selen Aug 22 '19 at 11:00
  • 6
    Well, it just so happens that the same C++ book will also answer your main problem. It will tell you exactly what an array is in C++ (hint: there's no really such thing as an array in C++, it's a mirage, the compiler sees your request to declare a "`uint16_t []`", smiles, and does something else completely), and what the relationships are between arrays and pointers. Without understanding how C++ works fundamentally, a simple answer here (return a pointer to a `uint16_t` ) won't really help you much. – Sam Varshavchik Aug 22 '19 at 11:02
  • *'there's no really such thing as an array in C++'* – errm... is it clear that this applies for function parameters and return values only? – Aconcagua Aug 22 '19 at 12:54

1 Answers1

7

Do not use Type[] ever. Use std::vector:

std::vector<uint16_t> GetIntArrayFromByteArray(std::vector<byte> byteArray)
{
    // If the number of bytes is not even, put a zero at the end
    if ((byteArray.size() % 2) == 1)
        byteArray.push_back(0);


    std::vector<uint16_t> intArray;

    for (int i = 0; i < byteArray.size(); i += 2)
        intArray.push_back((uint16_t)((byteArray[i] << 8) | byteArray[i + 1]));

    return intArray;
}

You can also use std::array<Type, Size> if the array would be fixed size.

More optimal version (thanks to @Aconcagua) (demo)

Here is a full code with more optimal version that doesn't copy or alter the input. This is better if you'll have long input arrays. It's possible to write it shorter, but I wanted to keep it verbose and beginner-friendly.

#include <iostream>
#include <vector>

using byte = unsigned char;

std::vector<uint16_t> GetIntArrayFromByteArray(const std::vector<byte>& byteArray)
{
    const int inputSize = byteArray.size();
    const bool inputIsOddCount = inputSize % 2 != 0;
    const int finalSize = (int)(inputSize/2.0 + 0.5);
    // Ignore the last odd item in loop and handle it later
    const int loopLength = inputIsOddCount ? inputSize - 1 : inputSize;

    std::vector<uint16_t> intArray;
    // Reserve space for all items
    intArray.reserve(finalSize);
    for (int i = 0; i < loopLength; i += 2) 
    {
      intArray.push_back((uint16_t)((byteArray[i] << 8) | byteArray[i + 1]));
    }

    // If the input was odd-count, we still have one byte to add, along with a zero
    if(inputIsOddCount) 
    {
      // The zero in this expression is redundant but illustrative
      intArray.push_back((uint16_t)((byteArray[inputSize-1] << 8) | 0));
    }
    return intArray;
}

int main() {
    const std::vector<byte> numbers{2,0,0,0,1,0,0,1};
    const std::vector<uint16_t> result(GetIntArrayFromByteArray(numbers));

    for(uint16_t num: result) {
        std::cout << num << "\n";
    }

    return 0;
}
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • `byteArray.pushBack(0)` is not correct, also why don't use `byteArray.size()` for the for-loop like the C# code intended – Ackdari Aug 22 '19 at 11:23
  • Why accept by value? By const reference would be pretty fine as well – solely that you would have to append the final zero to the new vector *after* the loop... And you should `reserve` sufficient capacity to prevent re-allocations. – Aconcagua Aug 22 '19 at 12:05
  • 1
    @Selen I created a more optimal version following the good points Aconcagua has made above. You should probably use it for larger input sizes. – Tomáš Zato Aug 22 '19 at 12:30