Search code examples
c#c++unsigned-integer

Method that returns uint16_t array properly in C++


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;
}

Solution

  • 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;
    }